[TOC]
## 11.1 语法
.JSON语法可以表示以下三种类型的值:
* 简单值:使用与JavaScript相同的语法,可以在JSON中表示字符串(双引)、数值(必须以十进制表示)、布尔值和null(不能使用NaN, Infinity, -Infinity和undefined)。但JSON不支持JavaScript中的特殊值undefined。
* 对象:对象作为一种复杂数据类型,表示的是一组无序的键值对。而每个键值对中的值可以是简单值,也可以是复杂数据类型的值。(键名必须在双引号内)
* 数组:数组也是一种复杂数据类型,表示一组有序的值的列表,可以通过数值索引来访问其中的值。(最后成员不加逗号)
### 11.1.1 简单值
最简单的JSON数据形式就是简单值。
~~~
5
"Hello world"
null
true
false
~~~
上面的都是有效的JSON数据。
### 11.1.2 对象
JSON中的对象与JavaScript中的对象字面量基本一样,除了JSON中的对象要求**对象的属性一定要加上双引号**。
JavaScript中的对象字面量:
~~~
标准形式
var object = {
name: "Nicholas",
age: 29;
};
或
var object = {
"name": "Nicholas",
"age": 29;
};
~~~
JSON中的对象字面量(没有声明,对象的属性必须加双引号,末尾没分好):
~~~
{
"name": "Nicholas",
"age": 29;
}
~~~
当然,可以使用嵌套对象:
~~~
{
"name": "Nicholas",
"age": 29,
"school": {
"name" : "Merrimack College",
"location": "North Andover, MA"
}
}
~~~
上面有两个同名(name)属性,这是没问题的,因为它们属于不同的对象。
**不同对象可以有同名属性,但同一对象内不能出现同名属性。**
### 11.1.3 数组
JSON数组采用的是JavaScript中的数组字面量,**也没有变量和分号**。
~~~
{
//JavaScript:
var values = [25,"hi",true];
//JSON
[25,"hi",true]
}
~~~
**还可以在数组中放对象,对象中放数组。**
## 11.2 解析与序列化
JSON在JavaScript中流行的原因是JSON数据结构可以解析成有用的JavaScript对象。
### 11.2.1 JSON对象
JSON是JavaScript语法的子集,因此eval()函数可以解析、解释并返回JavaScript对象和数组。
JSON对象有两个方法:`stringify()和parse()`。
JSON.stringify()把**JavaScript对象序列化为一个JSON字符串**(不包含任何空格字符或缩进)。
注意:在序列化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"}}
~~~
### 11.2.2 序列化选项
JSON.stringify()还接受额外两个参数,用于指定以不同的方式序列化JavaScript对象。
第二个参数是个过滤器,可以是一个数组,也可以是一个函数;第三个参数是一个选项,表示是否在JSON字符串中保留缩进。
**1. 过滤结果**
当传入的参数是**数组**时,那么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,那么相应的属性会被忽略。
**2. 字符串缩进**
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个字符。
**3. 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()方法,让toJSON()方法返回任何序列化的值。
假设将一个对象传入JSON.stringify(),序列化对象的顺序如下:
1. 如果存在toJSON()方法而且能通过它取得有效的值,则调用该方法,否则,按默认顺序序列化。
2. 如果提供了第二个参数,应用这个函数过滤器。传入函数过滤器的值是第1步返回的值
3. 对第2步返回的每个值进行相应的序列化
4. 如果提供了第三个参数,执行相应的格式化
### 11.2.3 解析选项
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,则表示要从结果中删除相应的键,如果返回其他值,则将其放入到结果中。
- 前言
- 第一章 JavaScript简介
- 第三章 基本概念
- 3.1-3.3 语法、关键字和变量
- 3.4 数据类型
- 3.5-3.6 操作符、流控制语句(暂略)
- 3.7函数
- 第四章 变量的值、作用域与内存问题
- 第五章 引用类型
- 5.1 Object类型
- 5.2 Array类型
- 5.3 Date类型
- 5.4 基本包装类型
- 5.5 单体内置对象
- 第六章 面向对象的程序设计
- 6.1 理解对象
- 6.2 创建对象
- 6.3 继承
- 第七章 函数
- 7.1 函数概述
- 7.2 闭包
- 7.3 私有变量
- 第八章 BOM
- 8.1 window对象
- 8.2 location对象
- 8.3 navigator、screen与history对象
- 第九章 DOM
- 9.1 节点层次
- 9.2 DOM操作技术
- 9.3 DOM扩展
- 9.4 DOM2和DOM3
- 第十章 事件
- 10.1 事件流
- 10.2 事件处理程序
- 10.3 事件对象
- 10.4 事件类型
- 第十一章 JSON
- 11.1-11.2 语法与序列化选项
- 第十二章 正则表达式
- 12.1 创建正则表达式
- 12.2-12.3 模式匹配与RegExp对象
- 第十三章 Ajax
- 13.1 XMLHttpRequest对象
- 你不知道的JavaScript
- 一、作用域与闭包
- 1.1 作用域
- 1.2 词法作用域
- 1.3 函数作用域与块作用域
- 1.4 提升
- 1.5 作用域闭包
- 二、this与对象原型
- 2.1 关于this
- 2.2 全面解析this
- 2.3 对象
- 2.4 混合对象“类”
- 2.5 原型
- 2.6 行为委托
- 三、类型与语法
- 3.1 类型
- 3.2 值
- 3.3 原生函数