你不知道的JSON.stringify

228 阅读3分钟

「这是我参与2022首次更文挑战的第8天,活动详情查看:2022首次更文挑战」。

1.JSON定义

引用MDN的定义

JSON 是一种语法,用来序列化对象、数组、数值、字符串、布尔值和 [null] 。JSON对象包含两个方法: 用于解析JSON的 parse() 方法,以及将对象/值转换为 JSON字符串的 stringify() 方法。除了这两个方法, JSON这个对象本身并没有其他作用,也不能被调用或者作为构造函数调用。

2.JSON对象

JSON是js中的一个全局对象,可以直接使用,对JSON使用typeof的结果是什么呢?

typeof JSON // 'object'

很明显,JSON是一个Object对象,那JSON的toString结果又是什么呢?

Object.prototype.toString.call(JSON) // '[object JSON]'

JSON对于基础类型来说,JSON序列化和toString的效果基本相同

JSON.stringify(12) // '12'
JSON.stringify("22") // '"22"'
JSON.stringify(null) // 'null'
JSON.stringify(false) // 'false'

3.JSON使用

所以安全的JSON值都可以使用JSON.stringify方法字符串化,安全的JSON值是指能够呈现为有效JSON的格式值。

不安全的JSON值有:undefined、function、symbol、和包含循环引用的对象

JSON.stringify(undefined) // undefined
JSON.stringify(function a(){}) // undefined
JSON.stringify(Symbol) // undefined
var a = {}
var b = { c: 1, a}
a.b = b
JSON.stringify(a) // 报错

前三个序列化都返回undefined,序列化包含循环引用对象会报错,JSON.stringify数组的时候,遇到undefined、function、symbol会返回null

JSON.stringify([1,2,undefined,function a(){},Symbol,3]) // '[1,2,null,null,null,3]'

如果对象中定义了toJSON方法,JSON序列化是会首先调用该方法,然后用它的返回值来进行序列化。

var b = { c: 1 }
b.toJSON = function() {
    return { a: 1 }
}
JSON.stringify(b) // '{"a":1}'

很多人都不知道JSON.stringify还可以传一个可选参数replacer,它可以是数组或函数,用来置顶对象序列化过程汇总哪些属性应该被处理,哪些应该被排除,和toJSON()很像。

如果replacer是一个数组,则它必须是一个字符串数组,数组中的元素为要处理对象的key值,除了数组中的key值,其它的属性将被排除。

var a = {
    b: 11,
    c: "22",
    d: [1,2,3]
}
JSON.stringify(a, ['c', 'd']) // '{"c":"22","d":[1,2,3]}'

如果replacer是一个函数,它会对对象本身调用一次,然后对对象中的每个属性各调用一次,每次传递两个参数,键和值。如果要忽略某个键就返回undefined。

var a = {
    b: 11,
    c: "22",
    d: [1,2,3]
}
var c = JSON.stringify(a, (key, value) => {
    console.log('key: ', key, 'value: ', value)
    return key !== 'b' ? value : void 0;
})
c // '{"c":"22","d":[1,2,3]}'
// 遍历结果
key:   value:  {b: 11, c: '22', d: Array(3)}
key:  b value:  11
key:  c value:  22
key:  d value:  (3) [1, 2, 3]
key:  0 value:  1
key:  1 value:  2
key:  2 value:  3

其中d对象本身会调用一次,d的属性也会调用一次

JSON.stringify还可以传一个可选参数space,用于指定输出的缩进格式。space为正整数时是指定每一级缩进的字符数,它还可以是字符串,字符串最前面的十个字符用于每一级的缩进。

var a = {
    b: 11,
    c: "22",
    d: [1,2,3]
}
JSON.stringify(a, null, 3)
// 
{
   "b": 11,
   "c": "22",
   "d": [
      1,
      2,
      3
   ]
}
JSON.stringify(a, null, '---')
//
{
---"b": 11,
---"c": "22",
---"d": [
------1,
------2,
------3
---]
}