前言
JavaScript开发人员都错误地把JavaScript对象字面量(Object Literals)称为JSON对象(JSON Objects),因为他的语法和JSON规范里描述的一样,但是该规范里也明确地说了JSON只是一个数据交换语言,只有我们将之用在string上下文的时候它才叫JSON。— 汤姆大叔
在正式介绍JSON之前我们可以先了解下JSON对值类型的规定
- 复合类型的值只能是数组或对象,不能是函数、正则表达式对象、日期对象。
- 原始类型的值只有四种:字符串、数值(必须以十进制表示)、布尔值和
null
(不能使用NaN
,Infinity
,-Infinity
和undefined
)。 - 字符串必须使用双引号表示,不能使用单引号。
- 对象的键名必须放在双引号里面。
- 数组或对象最后一个成员的后面,不能加逗号。
下面介绍的使用JSON的两个静态方法:
JSON.parse
用来将JSON字符串反序列化成对象,JSON.stringify
用来将对象序列化成JSON字符串JSON.stringify()
JSON.stringify()
方法用于将一个值转为 JSON 字符串。该字符串符合 JSON 格式,并且可以被JSON.parse()
方法还原。console.log(JSON.stringify('abc')) // "abc"
console.log(JSON.stringify(1)) // "1"
console.log(JSON.stringify(false)) // "false"
console.log(JSON.stringify([])) // "[]"
console.log(JSON.stringify({})) // "{}"
console.log(JSON.stringify([1, "false", false])) // '[1,"false",false]'
console.log(JSON.stringify({ name: "张三" })) // '{"name":"张三"}'
如果对象的属性是
undefined
、函数或XML对象,该属性会被JSON.stringify()
过滤。 ```javascript let obj = { a: undefined, b: function () {} };
console.log(JSON.stringify(obj)) // “{}”
- 如果数组的成员是`undefined`、函数或 XML 对象,则这些值被转成`null`
```javascript
let arr = [undefined, function () {}];
console.log(JSON.stringify(arr)) // "[null,null]"
正则会被转换为空对象
console.log(JSON.stringify(/foo/)) // "{}"
JSON.stringify()
方法会忽略对象的不可遍历的属性。 ```javascript let obj = {}; Object.defineProperties(obj, { ‘foo’: {value: 1,
enumerable: true
}, ‘bar’: {
value: 2,
enumerable: false
} });
console.log(JSON.stringify(obj)); // “{“foo”:1}”
<a name="qc6Sf"></a>
### 第二个参数
`JSON.stringify()`方法还可以接受一个数组,作为第二个参数,指定参数对象的哪些属性需要转成字符串。
```javascript
let obj = {
'prop1': 'value1',
'prop2': 'value2',
'prop3': 'value3'
};
let selectedProperties = ['prop1', 'prop2'];
console.log(JSON.stringify(obj, selectedProperties))
// "{"prop1":"value1","prop2":"value2"}"
类似白名单的数组,只对对象的属性有效,对数组无效
console.log(JSON.stringify(['a', 'b'], ['0']))
// "["a","b"]"
console.log(JSON.stringify({0: 'a', 1: 'b'}, ['0']))
// "{"0":"a"}"
第二个参数还可以是一个函数,用来更改
JSON.stringify()
的返回值。function f(key, value) {
if (typeof value === "number") {
value = 2 * value;
}
return value;
}
console.log(JSON.stringify({
a: 1,
b: 2
}, 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 // }
上述第三个属性`\t`在每个属性前面添加一个制表符,然后分行显示
- 第三个属性如果是一个数字,则表示每个属性前面添加的空格(最多不超过10个)
```javascript
console.log(JSON.stringify({
p1: 1,
p2: 2
}, null, 3));
/*
"{
"p1": 1,
"p2": 2
}"
*/
toJSON()方法
如果参数对象有自定义的toJSON()
方法,那么JSON.stringify()
会使用这个方法的返回值作为参数,而忽略原对象的其他属性。
let user = {
firstName: '三',
lastName: '张',
get fullName() {
return this.lastName + this.firstName;
},
toJSON: function() {
return {
name: this.lastName + this.firstName
}
}
};
console.log(JSON.stringify(user))
// {"name":"张三"}
JSON.parse()
JSON.prarse()
方法用于将JSON字符串转换成对应的值
console.log(JSON.parse('{}')) // {}
console.log(JSON.parse('true')) // true
console.log(JSON.parse('"foo"')) // "foo"
console.log(JSON.parse('[1, 5, "false"]')) // [1, 5, "false"]
console.log(JSON.parse('null')) // null
let o = JSON.parse('{"name": "张三"}');
console.log(o.name) // 张三
- 如果传入的字符串不是有效的 JSON 格式,
JSON.parse()
方法将报错。console.log(JSON.parse('String')) // 报错