JSON.stringify 的解析

JSON.stringify(value[, replacer [, space]]) 方法将一个 JavaScript 对象或值转换为 JSON 字符串,如果指定了一个 replacer 函数,则可以选择性地替换值,或者指定的 replacer 是数组,则可选择性地仅包含数组指定的属性。

Note 1

JSON.stringify 方法对对象进行序列化时,如果对象的属性是 undefined/Symbol 值或任意函数时,不会对其进行处理。

这会导致被序列化的对象中的属性并不会按照原定的顺序被输出。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
const someObj = {
_id: 'id',
productCode: 'P28120068',
productDetail: {
name: 'Star Insure',
price: 1200,
amount: 1000000
},
created_at: 'Fri Nov 13 2020 09:25:31 GMT+0800 (China Standard Time)',
updated_at: 'Fri Nov 13 2020 09:25:31 GMT+0800 (China Standard Time)',
nullValue: null,
undefinedValue: undefined, // JSON.stringify 不会序列化 undefined
symbolValue: Symbol('TypeScript'), // JSON.stringify 不会序列化 Symbol
arrowLog: () => console.log(this), // JSON.stringify 不会序列化 箭头函数
funLog: function() { console.log(this) }, // JSON.stringify 不会序列化 函数
}

/**
* Note 1 : undefined、Symbol、任何函数作为对象的属性值时,JSON.stringify 不对其(忽略)进行序列化
* {
* "_id":"id",
* "productCode":"P28120068",
* "productDetail":{"
* name":"Star Insure",
* "price":1200,
* "amount":1000000
* },
* "created_at":"Fri Nov 13 2020 09:25:31 GMT+0800 (China Standard Time)",
* "updated_at":"Fri Nov 13 2020 09:25:31 GMT+0800 (China Standard Time)",
* "nullValue":null
* }
*/
console.log(JSON.stringify(someObj));

Note 2

JSON.stringify 方法对数组进行序列化时,如果数组元素的值是 undefinedSymbol 值或任意函数时,会被序列化为 null

1
2
3
4
5
6
7
8
9
10
11
12
13
14
const someArr = [
null,
undefined, // JSON.stringify 将数组中的 undefined 序列化为 null
Symbol('TypeScript'), // JSON.stringify 将数组中的 Symbol 序列化为 null
() => console.log(this), // JSON.stringify 将数组中的 箭头函数 序列化为 null
function() { console.log(this) } // JSON.stringify 将数组中的 函数 序列化为 null
]

/**
* Note 2 : undefined, Symbol, 任意函数作为数组的元素时,JSON.stringify 将其序列化为 null
* [null,null,null,null,null]
*/
console.table(JSON.stringify(someArr));

Note 3

如果 undefinedSymbol 值或任意函数作为单独的值被 JSON.stringify 序列化为 undefined

1
2
3
4
5
6
/**
* Note 3 : undefined, Symbol, 任意函数作为单独的值时,JSON.stringify 序列化会返回 undefined
*/
console.log(JSON.stringify(undefined)); // undefined
console.log(JSON.stringify(Symbol('TypeScript'))); // undefined
console.log(JSON.stringify(() => console.log(this))); // undefined

Note 4

如果目标值有 toJSON 方法,则 toJSON 来决定 JSON.stringify 返回的值。

1
2
3
4
5
console.log(JSON.stringify({
name: 'Jimmy',
age: 20,
toJSON: () => 'this is a toJSON function',
})); // this is a toJSON function

Note 5

NaN, InInfinitynull 会被JSON.stringify 序列化为 null

1
2
3
4
5
6
7
8
9
/**
* NaN, InInfinity 及 null 会被 JSON.stringify 序列化为 null
*/
console.log(NaN); // NaN
console.log(JSON.stringify(NaN)); // null
console.log(Infinity); // Infinity
console.log(JSON.stringify(Infinity)); // null
console.log(null); // null
console.log(JSON.stringify(null)); // null

Note 6

数字、字符串和布尔值的包装值在被 JSON.stringify 序列化时会解包成对应的基础值。

1
2
3
const packArr = [ new Number(1), new String('TypeScript'), new Boolean(false)];
console.log(packArr); // [ [Number: 1], [String: 'TypeScript'], [Boolean: false] ]
console.log(JSON.stringify(packArr)); // [1,"TypeScript",false]

Note 7

JSON.stringify 在序列化对象时,仅会序列化可枚举的属。

1
2
3
4
5
const enumerableObj = Object.create(null, {
name: { value: 'jack', enumerable: true },
age: { value: 20, enumerable: false }
});
console.log(JSON.stringify(enumerableObj)); // { name: 'jack' }

Note 8

如果 JSON.stringify 的目标对象发生循环引用时,会报错。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/**
* 对于相互引用的对象,会报错
* TypeError: Converting circular structure to JSON
--> starting at object with constructor 'Object'
| property 'refA' -> object with constructor 'Object'
--- property 'refB' closes the circle
*/
const objA = {
name: 'Object A',
refB: null,
};

const objB = {
name: 'Object B',
refA: objA,
};

objA.refB = objB;

Note 9

Symbol 值为键的属性值,在被 JSON.stringify 序列化时会被忽略。

1
2
3
4
5
6
7
8
9
/**
* 以 Symbol 值为键的属性值,在被 JSON.stringify 序列化时会被忽略
*/
const symbolObj = {
name: 'Symbol',
[Symbol.for('Age')]: 20,
};
console.log(symbolObj); // { name: 'Symbol', [Symbol(Age)]: 20 }
console.log(JSON.stringify(symbolObj)); // {"name":"Symbol"}

Note 10

JSON.stringify 的第二个参数是函数时, 可单独对某个值进行处理。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
const someObj = {
_id: 'id',
productCode: 'P28120068',
productDetail: {
name: 'Star Insure',
price: 1200,
amount: 1000000
},
created_at: 'Fri Nov 13 2020 09:25:31 GMT+0800 (China Standard Time)',
updated_at: 'Fri Nov 13 2020 09:25:31 GMT+0800 (China Standard Time)',
nullValue: null,
undefinedValue: undefined, // JSON.stringify 不会序列化 undefined
symbolValue: Symbol('TypeScript'), // JSON.stringify 不会序列化 Symbol
arrowLog: () => console.log(this), // JSON.stringify 不会序列化 箭头函数
funLog: function() { console.log(this) }, // JSON.stringify 不会序列化 函数
}

/**
* 当 JSON.stringify 的第二个参数是函数时, 可单独对某个值进行处理
*/
console.log(JSON.stringify(someObj, (k, v) => {
console.log(v)
if (typeof v === 'undefined') return 'undefined';
return JSON.stringify(v);
}));

JSON.stringify 的第二个参数是数组时,可在数组中加入属性名,来规定返回哪些属性的序列化值。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
const someObj = {
_id: 'id',
productCode: 'P28120068',
productDetail: {
name: 'Star Insure',
price: 1200,
amount: 1000000
},
created_at: 'Fri Nov 13 2020 09:25:31 GMT+0800 (China Standard Time)',
updated_at: 'Fri Nov 13 2020 09:25:31 GMT+0800 (China Standard Time)',
nullValue: null,
undefinedValue: undefined, // JSON.stringify 不会序列化 undefined
symbolValue: Symbol('TypeScript'), // JSON.stringify 不会序列化 Symbol
arrowLog: () => console.log(this), // JSON.stringify 不会序列化 箭头函数
funLog: function() { console.log(this) }, // JSON.stringify 不会序列化 函数
}

/**
* 当 JSON.stringify 的第二个参数是数组时,可在数组中加入属性名,来规定返回哪些属性的序列化值
* 但当值是 undefined、Symbol、任何函数时无效
*/
console.log(JSON.stringify(someObj, ['productCode', 'arrowLog'])); // { productCode: 'P28120068' }
作者

Y2hlbmdsZWk=

发布于

2018-05-12

更新于

2021-09-01

许可协议