JSON.stringify 在日常开发中是经常遇到,但是你知道它其实有三个参数吗?
JSON.stringify(value, replacer, space)
我们一般只会用到第一个参数,即 value(被序列化的对象),后面两个参数是可选的。但是后面两个参数才是 JSON.stringify 有趣的地方。
replacer
第二个参数
replacer可以让我们定制序列化的逻辑。
默认情况下(该参数为 null 或 undefined),对象所有的属性都会被序列化,但是 replacer 还可以是函数或数组:
- 如果
replacer是一个函数,则在序列化过程中,被序列化的值的每个属性都会经过该函数的转换和处理; - 如果
replacer是一个数组,则只有包含在这个数组中的属性名才会被序列化到最终的 JSON 字符串中;
例如:
function replacer(key, value) {
if (typeof value === "string") {
return undefined
}
return value
}
var foo = {foundation: "Mozilla", model: "box", week: 45, transport: "car", month: 7}
var jsonString = JSON.stringify(foo, replacer) // {"week":45,"month":7}.
上面的 replacer 对需要序列化对象的字段起到了过滤作用,排除 string 类型的值,它是递归过滤的,比如把上面的 foo 对象修改一下:
var foo = {foundation: "Mozilla", model: {name: "box", week: 45, transport: "car"}, month: 7}
var jsonString = JSON.stringify(foo, replacer) // {"model":{"week":45},"month":7}
当 replacer 时函数的时候,它接收两个参数:键(key)和值(value),而它的返回值决定了该字段是否被序列化:
- 返回
Number,转换成相应的字符串被添加入 JSON 字符串。 - 返回
String,该字符串作为属性值被添加入 JSON。 - 返回
Boolean,"true" 或者 "false"被作为属性值被添加入 JSON 字符串。 - 返回任何其他对象,该对象递归地序列化成 JSON 字符串,对每个属性调用 replacer 方法。除非该对象是一个函数,这种情况将不会被序列化成 JSON 字符串。
- 返回
undefined,该属性值不会在 JSON 字符串中输出。
其他都好理解,返回对象是什么意思呢?
function replacer(key, value) {
if (key === "model") {
return {hello: "world", model: 3}
}
return value
}
var foo = {foundation: "Mozilla", model: {name: "box", week: 45, transport: "car"}, month: 7}
var jsonString = JSON.stringify(foo, replacer) // {"foundation":"Mozilla","model":{"hello":"world"},"month":7}
原来就是用新对象替换了原来 key 的值,但是需要注意的是,在替换之前也会对该对象使用 replacer 方法进行过滤,加入上面的 replacer 函数写成下面的形式就会报错 Maximum call stack size exceeded,因为出现了无限递归:
function replacer(key, value) {
if (key === "model") {
return {hello: "world", model: 3}
}
return value
}
改成:
let count = 0
function replacer(key, value) {
count++
if (typeof value === "string" && count < 5) {
return {name: "Davlid", count}
}
return value
}
var foo = {foundation: "Mozilla", model: {name: "box", week: 45, transport: "car"}, month: '7'}
var jsonString = JSON.stringify(foo, replacer)
上面的输出结果是:
{"foundation":{"name":{"name":{"name":"Davlid","count":4},"count":3},"count":2},"model":{"name":"box","week":45,"transport":"car"},"month":"7"}
replacer 除了可以是函数,还可以是数组:
var foo = {foundation: "Mozilla", model: "box", week: 45, transport: "car", month: 7}
JSON.stringify(foo, ['model', 'month']) // {"model":"box","month":7}
space
第三个参数
space可以让我们定制序列化的显示效果
space 用来控制结果字符串里面的间距,取值可以是一个数字或字符串:
- 如果是数字, 则在字符串化时每一级别会比上一级别缩进多这个数字值的空格(最多10个空格);
- 如果是字符串,则每一级别会比上一级别多缩进用该字符串(或该字符串的前十个字符)。
var foo = {foundation: "Mozilla", model: "box", week: 45, transport: "car", month: 7}
JSON.stringify(foo, null, 2)
会缩进2个空格,结果是:
{
"foundation": "Mozilla",
"model": "box",
"week": 45,
"transport": "car",
"month": 7
}
如果用:
var foo = {foundation: "Mozilla", model: "box", week: 45, transport: "car", month: 7}
JSON.stringify(foo, null, '$')
结果是:
{
$$"foundation": "Mozilla",
$$"model": "box",
$$"week": 45,
$$"transport": "car",
$$"month": 7
}