JSON对象(学习笔记打卡)

173 阅读5分钟

学习概要

  1. JSON格式

  2. JSON对象

  3. JSON.stringify()

    • 基本用法
    • 第二参数
    • 第三参数
    • 参数对象的toJSON()方法
  4. JSON.parse()

1 JSON格式

JSON对值的类型和格式有严格的规定

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

合法的JSON如下:

["one", "two", "three"] 
{ "one": 1, "two": 2, "three": 3 } 
{"names": ["张三", "李四"] } 
[ { "name": "张三"}, {"name": "李四"} ]
{"1":"lc","2":"zj"}

不合法的JSON如下

{ name: "张三", 'age': 32 } // 属性名必须使用双引号 
[32, 64, 128, 0xFFF] // 不能使用十六进制值 
{ "name": "张三", "age": undefined } // 不能使用 undefined 
{ 
    "name": "张三", 
    "birthday": new Date('Fri, 26 Aug 2011 07:13:10 GMT'), 
    "getName": function () { return this.name; } 
} // 属性值不能使用函数和日期对象 
{1:"lc",2:"zj"} // 属性名必须使用双引号

2 JSON对象

JSON对象是JavaScript的原生对象,用来处理JSON格式数据。他有两个方法:JSON.stringify()和JSON.parse()

3 JSON.stringify()

3.1 基本用法

将一个值转为JSON字符串,该字符串符合JSON格式,并可以用JSON.parse()还原

JSON.stringify('abc') // ""abc"" 
JSON.stringify(1) // "1" 
JSON.stringify(false) // "false" 
JSON.stringify([]) // "[]" 
JSON.stringify({}) // "{}" 
JSON.stringify([1, "false", false]) // '[1,"false",false]' 
JSON.stringify({ name: "张三" }) // '{"name":"张三"}'

注:对于原始类型的字符串,转换结果会带双引号(' "" ')

  • 如果对象的属性是undefined、函数或者symbol值(XML对象)在序列化过程中会被忽略
var obj = { 
    a: undefined, 
    b: function () {} 
}; 
JSON.stringify(obj) // "{}" 
// 结果都被JSON.stringify过滤
  • 如果数组的成员是undefined、函数或者symbol值(XML对象)在序列化过程中会被转为null
var arr = [undefined, function () {}]; 
JSON.stringify(arr) // "[null,null]"
  • 正则对象被转为空对象
JSON.stringify(/foo/) // "{}"
  • 会忽略对象中不可遍历的属性
var obj = {}; 
Object.defineProperties(obj, { 
    'foo': { value: 1, enumerable: true }, 
    'bar': { value: 2, enumerable: false //不可遍历属性 } 
}); 
JSON.stringify(obj); // "{"foo":1}"

3.2 第二个参数

  • 可以是数组,指定参数对象的哪些属性需要转成字符串
var obj = { 
    'name': 'zj', 
    'age': 18, 
    'hobby': 'lc' 
}; 
var arr = ['name', 'hobby']; 
JSON.stringify(obj, arr) // "{"name":"zj","hobby":"lc"}"

注,只对对象的属性有效,对数组无效

JSON.stringify(['a', 'b'], ['0']) // "["a","b"]" 
JSON.stringify({0: 'a', 1: 'b'}, ['0'])// "{"0":"a"}"
  • 还可以是一个函数,用来更改JSON.stringify的返回值
// 函数会被执行两次,首先会整个转换的对象传进去 
// 第一次,key不存在,value为{ a: 1, b: 2 }不是对象,返回{ a: 1, b: 2 } 
// 第二次,key为ab,value为12是数值,返回1*2=22*2=4 
// 最后是把{ a: 2, b: 4 }生成JSON字符串 
function f(key, value) { 
    if (typeof value === "number") { 
        value = 2 * value; 
    } 
    return value; 
} 
JSON.stringify({ a: 1, b: 2 }, f) // '{"a": 2,"b": 4}'

注,这个处理函数是递归处理所有的键。每一次处理的对象,都是前一次返回的值。

var obj = {a: 1}; 
// 函数会被执行两次,首先会整个转换的对象传进去 
// 第一次,key不存在,value为{a:1}是对象,返回{b:2} 
// 第二次,key为b,value为2不是对象,返回2*2=4 
// 最后是把{b:4}生成JSON字符串 
function f(key, value) { 
    if (typeof value === 'object') { 
        return {b: 2}; 
    } 
    return value * 2; 
} 
JSON.stringify(obj, f) // "{"b": 4}"

如果处理函数返回undefined或没有返回值,则该属性会被忽略。

function f(key, value) { 
    if (typeof(value) === "string") { 
        return undefined; 
    } 
    return value; 
} 
JSON.stringify({ a: "abc", b: 123 }, f) // '{"b": 123}'

3.3 第三个参数

用于增加返回的JSON字符串的可读性。(默认返回的是单行字符串,对于大型的 JSON 对象,可读性非常差。)

如果是一个数字,则在字符串化时每一级别会比上一级别缩进多这个数字值的空格(最多 10 个空格);如果是一个字符串,则每一级别会比上一级别多缩进该字符串(或该字符串的前 10 个字符)。

// 默认输出 
JSON.stringify({ p1: 1, p2: 2 }) // JSON.stringify({ p1: 1, p2: 2 }) 
// 分行输出 
JSON.stringify({ p1: 1, p2: 2 }, null, 2); 
/* 
"{ 
    "p1": 1, 
    "p2": 2 
}" 
*/ 
JSON.stringify({ p1: 1, p2: 2 }, null, '\t') 
// { 
//    "p1": 1, 
//    "p2": 2 
// }

3.4 参数对象的toJSON()方法

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

普通对象:

var user = { 
    firstName: 'j', 
    lastName: 'z', 
    get fullName(){ 
        return this.lastName + this.firstName; 
    } 
}; 
JSON.stringify(user) // "{"firstName":"j","lastName":"z","fullName":"zj"}"

加上toJSON()方法:

var user = { 
    firstName: 'j', 
    lastName: 'z', 
    get fullName(){ 
        return this.lastName + this.firstName; 
    }, 
    toJSON: function () { 
        return { 
            name: this.lastName + this.firstName 
        }; 
    } 
}; 
JSON.stringify(user) // "{"name":"zj"}"

Date有一个自己的toJSON()方法

var date = new Date('2023-02-28'); 
date.toJSON() // "2023-02-28T00:00:00.000Z" 
JSON.stringify(date) // '"2023-02-28T00:00:00.000Z"'

上面代码在正则对象的原型上面部署了toJSON()方法,将其指向toString()方法,因此转换成 JSON 格式时,正则对象就先调用toJSON()方法转为字符串,然后再被JSON.stringify()方法处理。

4 JSON.parse()

用于将JSON字符串转换成对象的值

JSON.parse('{}') // {} 
JSON.parse('true') // true 
JSON.parse('"foo"') // "foo" 
JSON.parse('[1, 5, "false"]') // [1, 5, "false"] 
JSON.parse('null') // null 

var o = JSON.parse('{"name": "张三"}'); 
o.name // 张三

传入字符串不是有效JSON格式,会报错

JSON.parse("'String'") // SyntaxError: Unexpected token ILLEGAL 
try { 
    JSON.parse("'String'"); 
} catch(e) { 
    console.log('parsing error'); 
}

可以接受一个处理函数,作为第二个参数,用法与JSON.stringify()方法类似。

function f(key, value) { 
    if (key === 'a') { 
        return value + 10; 
    } 
    return value; 
} 
JSON.parse('{"a": 1, "b": 2}', f) // {a: 11, b: 2}

本文笔记均来自网道JSON对象 部分来自MDN的JSON内容