JSON.stringify() 详解
JSON 的常规用途是同 web 服务器进行数据交换,在向 web 服务器发送数据时,数据必须是字符串。我们可以通过 JSON.stringify() 把 JavaScript 对象转换为字符串。
JSON.stringify()
语法
JSON.stringify(value[, replacer [, space]])
JSON.stringify()
不是只有一个参数,它最多可以有三个参数,只是一般后面两个用不到,所以我们会忽略它们。
value
将要序列化成 一个 JSON
字符串的值。
replacer [可选]
如果该参数是一个函数,则在序列化过程中,被序列化的值的每个属性都会经过该函数的转换和处理;如果该参数是一个数组,则只有包含在这个数组中的属性名才会被序列化到最终的 JSON
字符串中;如果该参数为 null
或者未提供,则对象所有的属性都会被序列化。
space [可选]
指定缩进用的空白字符串,用于美化输出(pretty-print);如果参数是个数字,它代表有多少的空格;上限为10。该值若小于1,则意味着没有空格;如果该参数为字符串(当字符串长度超过10个字母,取其前10个字母),该字符串将被作为空格;如果该参数没有提供(或者为 null),将没有空格。
JSON.stringify()转换规则
JSON.stringify()
将值转换为相应的JSON
格式:
- 转换值如果有 toJSON() 方法,该方法定义什么值将被序列化。
- 非数组对象的属性不能保证以特定的顺序出现在序列化后的字符串中。
- 布尔值、数字、字符串的包装对象在序列化过程中会自动转换成对应的原始值。
- undefined、任意的函数以及 symbol 值,在序列化过程中会5. 被忽略(出现在非数组对象的属性值中时)或者被转换成 null(出现在数组中时)。函数、undefined 被单独转换时,会返回 undefined,如JSON.stringify(function(){}) or JSON.stringify(undefined).
- 对包含循环引用的对象(对象之间相互引用,形成无限循环)执行此方法,会抛出错误。
- 所有以 symbol 为属性键的属性都会被完全忽略掉,即便 replacer 参数中强制指定包含了它们。
- Date 日期调用了 toJSON() 将其转换为了 string 字符串(同Date.toISOString()),因此会被当做字符串处理。
- NaN 和 Infinity 格式的数值及 null 都会被当做 null。
- 其他类型的对象,包括 Map/Set/WeakMap/WeakSet,仅会序列化可枚举的属性。
toJSON
let a = {
a: 1,
toJSON: function () {
return '哈哈哈。你怎么转都是这个'
}
}
JSON.stringify(a)
//""哈哈哈。你怎么转都是这个""
转换值如果有 toJSON()
函数,该函数返回什么值,序列化结果就是什么值,并且忽略其他属性的值。
非数组对象的属性不能保证以特定的顺序出现在序列化后的字符串中
//对象
JSON.stringify({
a: function () {
return '哈哈哈'
},
b: 1,
c: undefined
})
/**
*"{
* "b": 1
*}"
*/
//数组
JSON.stringify([function toJSON() {return '哈哈哈'}, 1, '', undefined])
//"[null,1,"",null]"
自动转换成对应的原始值
JSON.stringify([new Number(1), new String("true"), new Boolean(false)]);
//"[1,"true",false]"
undefined
、函数、symbol
转化
作为对象属性值时:
let data = {
a: "1",
b: undefined,
c: Symbol("c"),
fn: function() {
return 'this is JSON.stringfy';
}
};
JSON.stringify(data)
//"{"a":"1"}"
undefined
、函数、symbol
作为对象属性值JSON.stringify()
会忽略对它们的序列化。
作为数组元素值时:
let arr = ["1", undefined, function c() {
return 'this is JSON.stringfy'
}, Symbol('d')]
JSON.stringify(arr)
//"["1",null,null,null]"
undefined
、函数、symbol
作为数组元素时,JSON.stringify()
会将他们转为null。
单独转换时:
JSON.stringify(function a (){console.log('this is JSON.stringfy')})
JSON.stringify(undefined)
JSON.stringify(Symbol('symbol'))
//三者都是undefined
单独的值进行转化时会返回 undefined。
symbol
为属性键的属性都会被完全忽略掉
let symbolObj = {
[Symbol('test')]: "stringify"
}
JSON.stringify(symbolObj)
//"{}"
// 第二个参数replacer
JSON.stringify(symbolObj, function(k, v) {
if (typeof k == 'symbol') {return 'is symbol'}
})
//undefined
//toJSON
let symbolObj2 = {
[Symbol('test')]: "stringify",
toJSON: function () {
return 'to JSON 来强制转换'
}
}
JSON.stringify(symbolObj2)
//to JSON 来强制转换
以 symbol
为属性键的属性都会被完全忽略掉, replacer
指定也不行。
Date
JSON.stringify(new Date())
//""2020-08-06T07:03:30.155Z""
JSON.stringify({a: new Date()})
//"{"a":"2020-08-06T07:03:55.952Z"}"
NaN
、Infinity
和 null
JSON.stringify(NaN)
JSON.stringify(null)
JSON.stringify(Infinity)
//三者都是null
不可枚举的对象值
let enumerableObj = Object.create(
null,
{
x: { value: '不能枚举', enumerable: false },
y: { value: '可以枚举', enumerable: true }
}
)
JSON.stringify(enumerableObj)
// "{"y":"可以枚举"}"
//不可枚举的属性被忽略了
//用 replacer 第二参数看下
JSON.stringify(enumerableObj, (k, v) => {
console.log('k的值:', k, 'v的值:', v)
return v
})
// k的值: v的值: {y: "可以枚举", x: "不能枚举"}
// k的值: y v的值: 可以枚举
//结果
// "{"y":"可以枚举"}"