前言

JavaScript开发人员都错误地把JavaScript对象字面量(Object Literals)称为JSON对象(JSON Objects),因为他的语法和JSON规范里描述的一样,但是该规范里也明确地说了JSON只是一个数据交换语言,只有我们将之用在string上下文的时候它才叫JSON。— 汤姆大叔

在正式介绍JSON之前我们可以先了解下JSON对值类型的规定

  1. 复合类型的值只能是数组或对象,不能是函数、正则表达式对象、日期对象。
  2. 原始类型的值只有四种:字符串、数值(必须以十进制表示)、布尔值和null(不能使用NaN, Infinity, -Infinityundefined)。
  3. 字符串必须使用双引号表示,不能使用单引号。
  4. 对象的键名必须放在双引号里面。
  5. 数组或对象最后一个成员的后面,不能加逗号。

下面介绍的使用JSON的两个静态方法:

  • JSON.parse用来将JSON字符串反序列化成对象,
  • JSON.stringify用来将对象序列化成JSON字符串

    JSON.stringify()

    JSON.stringify()方法用于将一个值转为 JSON 字符串。该字符串符合 JSON 格式,并且可以被JSON.parse()方法还原。

    1. console.log(JSON.stringify('abc')) // "abc"
    2. console.log(JSON.stringify(1)) // "1"
    3. console.log(JSON.stringify(false)) // "false"
    4. console.log(JSON.stringify([])) // "[]"
    5. console.log(JSON.stringify({})) // "{}"
    6. console.log(JSON.stringify([1, "false", false])) // '[1,"false",false]'
    7. console.log(JSON.stringify({ name: "张三" })) // '{"name":"张三"}'
  • 如果对象的属性是undefined、函数或XML对象,该属性会被JSON.stringify()过滤。 ```javascript let obj = { a: undefined, b: function () {} };

console.log(JSON.stringify(obj)) // “{}”

  1. - 如果数组的成员是`undefined`、函数或 XML 对象,则这些值被转成`null`
  2. ```javascript
  3. let arr = [undefined, function () {}];
  4. console.log(JSON.stringify(arr)) // "[null,null]"
  • 正则会被转换为空对象

    1. console.log(JSON.stringify(/foo/)) // "{}"
  • JSON.stringify()方法会忽略对象的不可遍历的属性。 ```javascript let obj = {}; Object.defineProperties(obj, { ‘foo’: {

    1. value: 1,
    2. enumerable: true

    }, ‘bar’: {

    1. value: 2,
    2. enumerable: false

    } });

console.log(JSON.stringify(obj)); // “{“foo”:1}”

  1. <a name="qc6Sf"></a>
  2. ### 第二个参数
  3. `JSON.stringify()`方法还可以接受一个数组,作为第二个参数,指定参数对象的哪些属性需要转成字符串。
  4. ```javascript
  5. let obj = {
  6. 'prop1': 'value1',
  7. 'prop2': 'value2',
  8. 'prop3': 'value3'
  9. };
  10. let selectedProperties = ['prop1', 'prop2'];
  11. console.log(JSON.stringify(obj, selectedProperties))
  12. // "{"prop1":"value1","prop2":"value2"}"
  • 类似白名单的数组,只对对象的属性有效,对数组无效

    1. console.log(JSON.stringify(['a', 'b'], ['0']))
    2. // "["a","b"]"
    3. console.log(JSON.stringify({0: 'a', 1: 'b'}, ['0']))
    4. // "{"0":"a"}"
  • 第二个参数还可以是一个函数,用来更改JSON.stringify()的返回值。

    1. function f(key, value) {
    2. if (typeof value === "number") {
    3. value = 2 * value;
    4. }
    5. return value;
    6. }
    7. console.log(JSON.stringify({
    8. a: 1,
    9. b: 2
    10. }, f)) // '{"a": 2,"b": 4}'

    第三个参数

    JSON.stringify()还可以接受第三个参数,用于增加返回的 JSON 字符串的可读性。
    默认返回的是单行字符串,对于大型的 JSON 对象,可读性非常差。第三个参数使得每个属性单独占据一行,并且将每个属性前面添加指定的前缀(不超过10个字符)。 ```javascript // 默认输出 console.log(JSON.stringify({ p1: 1, p2: 2 })) // JSON.stringify({ p1: 1, p2: 2 })

// 分行输出 console.log(JSON.stringify({ p1: 1, p2: 2 }, null, ‘\t’)) // { // “p1”: 1, // “p2”: 2 // }

  1. 上述第三个属性`\t`在每个属性前面添加一个制表符,然后分行显示
  2. - 第三个属性如果是一个数字,则表示每个属性前面添加的空格(最多不超过10个)
  3. ```javascript
  4. console.log(JSON.stringify({
  5. p1: 1,
  6. p2: 2
  7. }, null, 3));
  8. /*
  9. "{
  10. "p1": 1,
  11. "p2": 2
  12. }"
  13. */

toJSON()方法

如果参数对象有自定义的toJSON()方法,那么JSON.stringify()会使用这个方法的返回值作为参数,而忽略原对象的其他属性。

  1. let user = {
  2. firstName: '三',
  3. lastName: '张',
  4. get fullName() {
  5. return this.lastName + this.firstName;
  6. },
  7. toJSON: function() {
  8. return {
  9. name: this.lastName + this.firstName
  10. }
  11. }
  12. };
  13. console.log(JSON.stringify(user))
  14. // {"name":"张三"}

JSON.parse()

JSON.prarse()方法用于将JSON字符串转换成对应的值

  1. console.log(JSON.parse('{}')) // {}
  2. console.log(JSON.parse('true')) // true
  3. console.log(JSON.parse('"foo"')) // "foo"
  4. console.log(JSON.parse('[1, 5, "false"]')) // [1, 5, "false"]
  5. console.log(JSON.parse('null')) // null
  6. let o = JSON.parse('{"name": "张三"}');
  7. console.log(o.name) // 张三
  • 如果传入的字符串不是有效的 JSON 格式,JSON.parse()方法将报错。
    1. console.log(JSON.parse('String')) // 报错

参考链接:
深入理解JavaScript系列(9):根本没有”JSON对象”这回事!