Skip to main content

详解 JSON.stringify 和 JSON.parse

不可被序列化的类型

JSON.stringify 和 JSON.parse 一起使用的作用是深拷贝,但是这个是有弊端的,并不是所有的值都可以被序列化

undefinedFunctionSymbol 在对象里面的话 ,JSON.parse 后会直接忽略掉,如下

const obj = {
name: 'A',
name1:
,
name3: function() {},
name4: Symbol('A'),
name5: RegExp('ab+c', 'i'),
name6: Date('1995-12-17T03:24:00')
}
const obj2 = JSON.parse(JSON.stringify(obj));

undefinedFunctionSymbol 三种类型在对象中被忽略,RegExp 类型会返回为空对象,Date(转换后变成了字符串,而非 Date 类的对象)

并且如果有循环引用类型的话还会报错,如下

const a = { key: 'value' };
a['a'] = a;
JSON.stringify(a);

// Uncaught TypeError: Converting circular structure to JSON
// --> starting at object with constructor 'Object'
// --- property 'a' closes the circle
// at JSON.stringify (<anonymous>)

循环引用类型

JSON.stringify 是不能识别循环引用类型的,如果一定要使用循环引用类型去序列化,可以添加 ,toJSON 方法,这个方法主要是为了在循环引用的时候返回一个合理的值

const a = { key: 'value',toJSON() {return '这个是 toJSON 的返回'}};
a['a'] = a;
console.log(JSON.stringify(a))

JSON.stringify 的第二个参数

JSON.stringify 是有第二个参数的 replacer,第二个参数可以写数组或者是函数,来指定序列化的值哪些需要被处理

函数

如果是函数的话,需要对对象里面的所有属性都调用一次,每次传递两个参数(第一个参数 k 是属性名字,v 是值),如果需要忽略哪个属性就把这个属性返回 undefined

const obj = {
a: 42,
b: 30,
c: 100,
};
JSON.stringify(obj, (k, v) => {
// 注意:第一次 k 是 undefined,v 是原对象
if (k !== 'c') return v;
}); // "{"a":42,"b":30}"

数组

如果第二个参数是数组的话,那么只需要传递属性的名字就可以指定对象需要返回的属性

const obj = {
a: 42,
b: 30,
c: 100,
};
JSON.stringify(obj, ['a', 'c']); // {"a":42,"c":100}