学透JSON.stringify
基本概念
JSON.stringify()
方法将一个JavaScript 对象
或值
转换为 JSON 字符串,如果指定了一个 replacer 函数,则可以选择性地替换值,或者指定的 replacer 是数组,则可选择性地仅包含数组指定的属性。
以下信息来自MDN
语法
JSON.stringify(value[, replacer [, space]])
参数
value
将要序列化成 一个 JSON 字符串的值。
replacer
可选
- 如果该参数是一个函数,则在序列化过程中,被序列化的值的每个属性都会经过该函数的转换和处理;
- 如果该参数是一个数组,则只有包含在这个数组中的属性名才会被序列化到最终的 JSON 字符串中;
- 如果该参数为 null 或者未提供,则对象所有的属性都会被序列化。
space
可选
- 指定缩进用的空白字符串,用于美化输出(pretty-print);
- 如果参数是个数字,它代表有多少的空格;上限为10。
- 该值若小于1,则意味着没有空格;
- 如果该参数为字符串(当字符串长度超过10个字母,取其前10个字母),该字符串将被作为空格;
- 如果该参数没有提供(或者为 null),将没有空格。
返回值
异常
TypeError
("cyclic object value")(循环对象值)BigInt
类型的值会抛出TypeError
("BigInt value can't be serialized in JSON")(BigInt值不能JSON序列化).基本使用
我经常使用JSON.stringify在vue中对对象进行深拷贝。对数据副本进行编辑。
注意
- JSON.stringify可以转换对象或者值(平常用的更多的是转换对象)
- 可以指定
replacer
为函数选择性的地替换 - 也可以指定
replacer
为数组,可转换指定的属性
这里仅仅是MDN上关于JSON.stringify
其中最基础的说明,咱们先打个码试试这几个特性
// 1. 转换对象
console.log(JSON.stringify({ name: 'wubin.work', sex: 'boy' })) // '{"name":"wubin.work","sex":"boy"}'
// 2. 转换普通值
console.log(JSON.stringify('wubin.work')) // "wubin.work"
console.log(JSON.stringify(1)) // "1"
console.log(JSON.stringify(true)) // "true"
console.log(JSON.stringify(null)) // "null"
// 3. 指定replacer函数
console.log(JSON.stringify({ name: 'wubin.work', sex: 'boy', age: 100 }, (key, value) => {
return typeof value === 'number' ? undefined : value
}))
// '{"name":"wubin.work","sex":"boy"}'
// 4. 指定数组
console.log(JSON.stringify({ name: 'wubin.work', sex: 'boy', age: 100 }, [ 'name' ]))
// '{"name":"wubin.work"}'
// 5. 指定space(美化输出)
console.log(JSON.stringify({ name: 'wubin.work', sex: 'boy', age: 100 }))
// '{"name":"wubin.work","sex":"boy","age":100}'
console.log(JSON.stringify({ name: 'wubin.work', sex: 'boy', age: 100 }, null , 2))
/*
{
"name": "wubin.work",
"sex": "boy",
"age": 100
}
*/
例如,对一个对象执行一个过滤函数,将value字段值等于undefined的替换为空:
let signInfo = [
{
fieldId: 539,
value: undefined
},
{
fieldId: 540,
value: undefined
},
{
fieldId: 546,
value: undefined
},
]
// 判断到value为undefined,返回空字符串即可
JSON.stringify(signInfo, (key, value) => typeof value === 'undefined' ? '' : value)
// '[{"fieldId":539,"value":""},{"fieldId":540,"value":""},{"fieldId":546,"value":""}]'
9大特性要记住
前仅仅是使用了这个方法,却没有详细了解他的转换规则,居然有9个之多。
特性一
undefined
、任意的函数
以及symbol值
,出现在非数组对象
的属性值中时在序列化过程中会被忽略undefined
、任意的函数
以及symbol值
出现在数组
中时会被转换成null
。undefined
、任意的函数
以及symbol值
被单独转换
时,会返回 undefined
// 1. 对象中存在这三种值会被忽略
console.log(JSON.stringify({
name: 'wubin.work',
sex: 'boy',
// 函数会被忽略
showName () {
console.log('wubin.work')
},
// undefined会被忽略
age: undefined,
// Symbol会被忽略
symbolName: Symbol('wubin.work')
}))
// '{"name":"wubin.work","sex":"boy"}'
// 2. 数组中存在着三种值会被转化为null
console.log(JSON.stringify([
'wubin.work',
'boy',
// 函数会被转化为null
function showName () {
console.log('wubin.work')
},
//undefined会被转化为null
undefined,
//Symbol会被转化为null
Symbol('wubin.work')
]))
// '["wubin.work","boy",null,null,null]'
// 3.单独转换会返回undefined
console.log(JSON.stringify(
function showName () {
console.log('wubin.work')
}
)) // undefined
console.log(JSON.stringify(undefined)) // undefined
console.log(JSON.stringify(Symbol('wubin.work'))) // undefined
特性二
布尔值
、数字
、字符串
的包装对象在序列化过程中会自动转换成对应的原始值。
console.log(JSON.stringify([new Number(1), new String("wubin.work"), new Boolean(false)]))
// '[1,"wubin.work",false]'
特性三
所有以symbol
为属性键的属性都会被完全忽略掉,即便replacer
参数中强制指定包含了它们。
console.log(JSON.stringify({
name: Symbol('wubin.work'),
}))
// '{}'
console.log(JSON.stringify({
[ Symbol('wubin.work') ]: 'wubin.work',
}, (key, value) => {
if (typeof key === 'symbol') {
return value
}
}))
// undefined
特性四
NaN 和 Infinity 格式的数值及 null 都会被当做 null。
console.log(JSON.stringify({
age: NaN,
age2: Infinity,
name: null
}))
// '{"age":null,"age2":null,"name":null}'
特性五
转换值如果有 toJSON() 方法,该方法定义什么值将被序列化。
const toJSONObj = {
name: 'wubin.work',
toJSON () {
return 'JSON.stringify'
}
}
console.log(JSON.stringify(toJSONObj))
// "JSON.stringify"
特性六
Date 日期调用了 toJSON() 将其转换为了 string 字符串(同Date.toISOString()),因此会被当做字符串处理。
const d = new Date()
console.log(d.toJSON()) // 2021-10-05T14:01:23.932Z
console.log(JSON.stringify(d)) // "2021-10-05T14:01:23.932Z"
特性七
对包含循环引用的对象(对象之间相互引用,形成无限循环)执行此方法,会抛出错误。
let cyclicObj = {
name: 'wubin.work',
}
cyclicObj.obj = cyclicObj
console.log(JSON.stringify(cyclicObj))
// Converting circular structure to JSON
特性八
其他类型的对象,包括 Map/Set/WeakMap/WeakSet,仅会序列化可枚举的属性
let enumerableObj = {}
Object.defineProperties(enumerableObj, {
name: {
value: 'wubin.work',
enumerable: true
},
sex: {
value: 'boy',
enumerable: false
},
})
console.log(JSON.stringify(enumerableObj))
// '{"name":"wubin.work"}'
特性九
当尝试去转换BigInt
类型的值会抛出错误
const alsoHuge = BigInt(9007199254740991)
console.log(JSON.stringify(alsoHuge))
// TypeError: Do not know how to serialize a BigInt