JSON
最后更新于:2022-04-01 23:53:55
## JSON
JSON(JavaScript Object Notation,JavaScript对象表示法),它是JavaScript的一个严格子集。
JSON只是一种简单数据格式,并不是只有JavaScript拥有。
**1、语法**
JSON对值的类型和格式有严格的规定:
- 复合类型的值只能是数组或对象,不能是函数、正则表达式对象、日期对象。
- 简单类型的值只有四种:字符串、数值(必须以十进制表示)、布尔值和null(不能使用NaN, Infinity, -Infinity和undefined)。
- 字符串必须使用双引号表示,不能使用单引号。
- 对象的键名必须放在双引号里面。
- 数组或对象最后一个成员的后面,不能加逗号。
**1.1 简单值**
最简单的JSON数据形式就是简单值。
```
5
"tg"
null
true
false
```
上面的都是有效的JSON数据。
**1.2 对象**
JSON中的对象与JavaScript中的对象字面量基本一样,除了JSON中的对象要求对象的属性一定要加上双引号(对象字面量的属性对引号可有可无)。
```
{
name: "tg"
}
{
'name': "tg"
}
```
上面两个对象对于JSON来说是错误的,正确的写法如下:
```
{
"name": "tg"
}
```
当然,你可以使用嵌套对象:
```
{
"name": "tg",
"school": {
"name": "tg",
"location": "gz"
}
}
```
可能你注意到了,上面有两个同名(name)属性,这是没问题的,因为它们属于不同的对象,但是请注意,同一对象内不能出现两个同名属性。
**1.3 数组**
JSON数组采用的是JavaScript中的数组字面量。
```
{
"color": ["red","blue"]
}
```
当然,你也可以在数组中放对象,对象中放数组。
**2、 解析与序列化**
JSON在JavaScript中流行的原因是JSON数据结构可以解析成有用的JavaScript对象。
**2.1序列化和反序列化**
JSON对象有两个方法:`JSON.stingify()`和`JSON.parse()`,分别表示将JavaScript对象序列化为JSON字符串和把JSON字符串解析为原生的JavaScript值。
**2.1.1 JSON.stringify()**
**(1)基本用法**
`JSON.stringify`方法用于将一个Javascript对象序列化为字符串。该字符串应该符合JSON格式,并且可以被`JSON.parse`方法还原。
注意:在序列化JavaScript对象时,所有函数及原型成员都会被有意忽略,不体现在结果中,而且值为undefined的任何属性也会被跳过,还有正则对象会被转成空对象。,最终返回来的值为有效的JSON格式。
```
var data = {
name: 'tg',
age: 1,
books: [ "Javascript", 2],
location:{
name: "gz",
},
test: function(){},
sex: undefined
};
console.log(JSON.stringify(data));
//{"name":"tg","age":1,"books":["Javascript",2],"location":{"name":"gz"}}
```
在上面的例子中,将data对象转换成JSON字符串,我们可以看到,键名都被双引号括起来了,而对于原始类型的字符串(name: 'tg'),也由单引号转成了双引号,这是因为将来还原的时候,双引号可以让JavaScript引擎知道,tg是一个字符串,而不是一个变量名。而且test和sex并没有在返回值中,这是因为test是函数,而sex的值是undefined。
**(2)过滤结果**
`JSON.stringify()`还可以接受第二个参数,指定需要转成字符串的属性。
当传入的参数是`数组`时,那么JSON.stringify()的结果中将只包含数组中列出的属性。
例子:
```
var data = {
name: 'tg',
age: 1,
books: [ "Javascript", 2],
location:{
name: "gz",
},
test: function(){},
sex: undefined
};
console.log(JSON.stringify(data,["name","books"]));
//{"name":"tg","books":["Javascript",2]}
```
在上面的例子中,传给JSON.stringify()的第二个参数是一个数组,其中包含两个字符串:“name”和“books”,这两个属性与将要序列化的对象中的属性是对应的,因此在返回的结果字符串中,就只会包含这两个属性(如上结果)。
第二个参数还可以是函数,它接收两个参数:属性(键)名和属性值,返回的值就是相应键的值(它改变了序列化对象的结果)。
属性名只能是字符串,而在值并非键值对的值时,键名可以是空字符串。
```
var jsonText = JSON.stringify(data,function(key, value){
if(key == 'books'){
return value.join(',');
}else{
return value;
}
});
console.log(jsonText);
//{"name":"tg","age":1,"books":"Javascript,2","location":{"name":"gz"}}
```
在上面的例子中,如果键名为"books",就将数组连成一个字符串,否则,返回原值。
注意:如果函数返回了undefined,那么相应的属性会被忽略。
**(3)字符串缩进**
JSON.stringify()方法还可以接收第三个参数,用于控制结果中的缩进和空白符。如果这个参数是数值,那它表示的是每个级别缩进的空格数。比如,要在每个级别缩进4个空格:
```
var data = {
name: 'tg',
age: 1,
books: [ "Javascript", 2],
location:{
name: "gz",
},
test: function(){},
sex: undefined
};
console.log(JSON.stringify(data, null, 4));
// 结果
{
"name": "tg",
"age": 1,
"books": [
"Javascript",
2
],
"location": {
"name": "gz"
}
}
```
当传入有效的控制缩进的参数值时,结果字符串就会自动包含换行符。不过要注意:最大缩进空格数为10,所有大于10的值都会自动转换为10.
如果缩进参数是一个字符串而非数值,则这个字符串将在JSON字符串中被用作缩进字符。
例子:
```
var data = {
name: 'tg',
age: 1,
books: [ "Javascript", 2],
location:{
name: "gz",
},
test: function(){},
sex: undefined
};
console.log(JSON.stringify(data, null, 4));
// 结果
{
--"name": "tg",
--"age": 1,
--"books": [
----"Javascript",
----2
--],
--"location": {
----"name": "gz"
--}
}
```
注意:缩进字符串最长不能超过10个字符长,如果超过了10个,结果中只会显示10个字符。
**(4)toJSON()方法**
如果JSON.stringify的参数对象有自定义的toJSON方法,那么JSON.stringify会使用这个方法的返回值作为参数,而忽略原对象的其他属性。
```
var data = {
name: 'tg',
age: 1,
toJSON:function(){
var data = {
name: this.name
};
return data;
}
};
console.log(JSON.stringify(data));
//{"name":"tg"}
```
在上面的代码中,我们给data对象定义了一个toJSON()方法,该方法返回name的值。
可以让toJSON()方法返回任何序列化的值。
假设将一个对象传入JSON.stringify(),序列化对象的顺序如下:
- 如果存在toJSON()方法而且能通过它取得有效的值,则调用该方法,否则,按默认顺序序列化。
- 如果提供了第二个参数,应用这个函数过滤器。传入函数过滤器的值是第(1)步返回的值
- 对第(2)步返回的每个值进行相应的序列化
- 如果提供了第三个参数,执行相应的格式化
**2.1.2 JSON.parse()**
`JSON.parse`方法用于将JSON字符串转化成原生的JavaScript对象。
例子:
```
var jsonText = '{"name":"tg","age":1,"books":["Javascript",2],"location":{"name":"gz"}}';
console.log(JSON.parse(jsonText));
//返回对象
{
name: 'tg',
age: 1,
books: [ "Javascript", 2],
location:{
name: "gz",
}
};
```
如果传入的字符串不是有效的JSON格式,则会报错。
JSON.parse()也可以接收另一个参数,该参数是一个函数,将在每个键值对上调用。
例子:
```
var jsonText = '{"name":"tg","age":1,"books":["Javascript",2],"location":{"name":"gz"}};
var o =JSON.parse(jsonText,function(key, value){
if(key == "name"){
return "Hello";
}
return value;
});
console.log(o.name);
// Hello
```
在上面的例子中,在解析时,当遇到键名是“name”时,就将相应的值替换成"Hello",最终返回的name就是"Hello"。
如果函数返回undefined,则表示要从结果中删除相应的键,如果返回其他值,则将其放入到结果中。
';