关于JSON.stringify()最常见的用法,应该通过JSON.parse(JSON.stringify())来做对象的拷贝,但是关于JSON.stringify()实际还有很多用法。在开始之前,先来看一段简单的代码:
javascript
JSON.stringify({
"reqId": "f67271bedd2041e79ed3754dcc5319db",
"partnerId": "P80000001",
"reqData": {
"issuerType": 1,
"issuerId": "9915",
"ticketDesc": "10减2元券",
"startTime": "2023-03-10",
"endTime": "2023-03-21",
"status": 0,
"hostInstNo": "",
"currPage": 1,
"pageSize": 100
},
"signType": "MD5",
"timestamp": "201809112345",
"sign": "EF7B56F75FA05FA07C8DB189518F0069"
}, null, 4)
可以看见,这段代码是没有格式化的,但是输出的结果却是正常空格格式化的。
这就是今天要说的关于JSON.stringify()的用法之一。
一、关于JSON.stringify的几个特性
1、JSON.stringify在处理undefined、函数、symbol、正则、Error特殊值时的不同表现
(1)、当undefined、函数、symbol三个特殊值作为对象属性值时:
javascript
JSON.stringify({
one: 'aaa',
two: undefined,
three: Symbol('333'),
four: function(){
return 1
}
})
// 输出结果
'{"one":"aaa"}'
可以得出结论:当undefined、函数、symbol作为对象属性值时,JSON.stringify()会直接直接忽略掉
(2)、当undefined、函数、symbol三个特殊值作为数组元素时:
javascript
JSON.stringify([1, 2, undefined, Symbol(3), function(){return 4}])
// 输出结果:
'[1,2,null,null,null]'
可以得出结论:当undefined、函数、symbol作为数组元素时,JSON.stringify()会直接将其序列化为null
(3)、当undefined、函数、symbol三个特殊值单独序列化时:
javascript
JSON.stringify(undefined)
// 输出结果
undefined
JSON.stringify(Symbol('123'))
// 输出结果
undefined
JSON.stringify(function(){return true})
// 输出结果
undefined
可以得出结论:当undefined、函数、symbol单独进行序列化时,JSON.stringify()会直接将其序列化为undefined
(4)、当存在正则、Error对象时,无论是作为对象值、数组元素还是单独序列化,都只会返回空对象
css
let obj = {
a: 'a',
b: 'b',
reg: new RegExp('\w+'),
err: new Error('error')
}
JSON.stringify(obj)
// 输出结果
'{"a":"a","b":"b","reg":{},"err":{}}'
根据其这一特性,我们日常在使用深拷贝方法或者进行序列化的时候,就要考虑是否有这几种特殊类型值存在,如果存在需要用特殊方法处理(后边会介绍)
2、当转换值中有toJSON()方法时,序列化的结果就是该方法的返回值,会忽略掉其他属性。
javascript
JSON.stringify({
name: 'lilei',
age: 12,
toJSON: function(){
return 'hanmeimei 14'
}
})
// 输出结果
'"hanmeimei 14"'
3、对于Date的值,JSON.stringify()会正常输出
css
JSON.stringify({time: new Date()})
// 输出结果
'{"time":"2024-04-01T08:18:39.722Z"}'
可以看到对于Date输出了正常的日期值,是因为Date对象内部有自己的toJSON()方法,相当于Date对象被当做了普通的字符串去处理。
4、对于NaN、Infinity、null,无论是作为对象的值、数组的元素还是单独序列化,都会被当做null
json
JSON.stringify({
one: NaN,
twu: Infinity,
three: null
})
// 输出结果
'{"one":"null","two":null,"three":null}'
5、如果存在属性可枚举和不可枚举的对象,仅会序列化可枚举属性
php
JSON.stringify(
Object.create(
null,
{
a: { value: 'aaa', enumerable: false },
b: { value: 'bbb', enumerable: true }
}
)
)
// 输出结果
'{"b":"bbb"}'
6、当使用JSPN.parse(JSON.stringify())进行对象拷贝时,注意循环引用问题,关于解决方法可以通过添加序列号、删除属性值、控制序列化深度等,具体情况具体分析。
二、关于JSON.stringify()的第二个和第三个参数
1、第二个参数replacer
第二个参数可以是一个数组,也可以是一个函数。
(1)当是数组时,数组的值代表着将被序列化成JSON字符串的属性名。
csharp
let obj = {
name: 'json',
params: 'stringfy params'
}
JSON.stringify(obj, ['name'])
// 输出结果
'{"name":"json"}'
(2)当时函数时,可以改变上边说的相关特性,对于undefined、Symbol、函数类型(无论作为对象值、还是数组元素)、正则、Error,可以使其返回定义的值
javascript
const data = {
a: "aaa",
b: undefined,
c: Symbol("234"),
fn: function() {
return true;
},
reg: new RegExp('\w+'),
err: new Error('error')
};
// 使用 replacer 参数作为函数时
JSON.stringify(data, (key, value) => {
switch (true) {
case typeof value === "undefined":
return "undefined";
case typeof value === "symbol":
return value.toString();
case typeof value === "function":
return value.toString();
case Object . prototype . toString . call ( value) === "[object Error]":
return 'error';
case Object . prototype . toString . call (value) === "[object RegExp]" :
return 'regexp';
default:
break;
}
return value;
})
// 输出结果
'{"a":"aaa","b":"undefined","c":"Symbol(234)","fn":"function() {\n return true;\n }","reg":"regexp","err":"error"}'
// 未使用第二个参数时,只会输出 "{"a":"aaa"}"
特殊情况:如果对象的属性是个Symbol,那么这个属性值也会直接被忽略掉,即使采用函数方法强制返回值也是无效的。
javascript
JSON.stringify({[Symbol.for("json")]: "symbolstring"}, function(k, v) {
if (typeof k === "symbol") {
return v;
}
})
// 输出结果
undefined
注意:replacer被传入为函数时,函数参数对应的第一对key/value并不是对象的第一个属性,key值是一个空字符串,value值是整个对象键值对;从第二个开始的key/value才是对应数据的属性值。
yaml
const data = { a : 2 , b : 3 , c : 4 , d : 5 }; JSON . stringify (data, ( key, value ) => { console . log ( 'key:' , key, 'value:' , value); return value; })
// console打印出内容
key: value: {a: 2, b: 3, c: 4, d: 5}
key: a value: 2
key: b value: 3
key: c value: 4
key: d value: 5
2、第三个参数
第三个参数space主要用来控制结果的间距,或者是添加一些特殊标识。
javascript
let obj = {
a: 1, b: 2, c: 3, d: 4
}
JSON.stringify(obj, null, 2)
JSON.stringify(obj, null, '**')
// 输出结果
' {
"a" : 1 ,
"b" : 2 ,
"c" : 3 ,
"d": 4
} '
'{
**"a": 1,
**"b": 2,
**"c": 3,
**"d": 4
}'
注意:space是有长度限制的,最大长度是10,但是超过10也不会报错。
如果传入的是数值并且超过10,其最多只会缩进10个空格; 如果传入的是字符串并且长度超过10,则只会截取前十个字符;
虽然日常开发中使用比较少,但是大概知道用法,在使用的时候还是很方便的~