学习概要
-
JSON格式
-
JSON对象
-
JSON.stringify()
- 基本用法
- 第二参数
- 第三参数
- 参数对象的toJSON()方法
-
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为a和b,value为1和2是数值,返回1*2=2和2*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}