Skip to content

Commit d1c8acd

Browse files
committed
JSON详解
1 parent 2f4ed97 commit d1c8acd

5 files changed

Lines changed: 392 additions & 7 deletions

File tree

JSON/JSON语法.md

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
**JSON语法**
2+
3+
JSON 的语法可以表示以下三种类型的值。
4+
5+
- 简单值:使用与 JavaScript 相同的语法,可以在 JSON 中表示字符串、数值、布尔值和 null 。但 JSON 不支持 JavaScript 中的特殊值 undefined 。
6+
- 对象:对象作为一种复杂数据类型,表示的是一组无序的键值对儿。而每个键值对儿中的值可以是简单值,也可以是复杂数据类型的值。
7+
- 数组:数组也是一种复杂数据类型,表示一组有序的值的列表,可以通过数值索引来访问其中的值。数组的值也可以是任意类型——简单值、对象或数组。
8+
9+
** JSON 不支持变量、函数或对象实例,它就是一种表示结构化数据的格式,虽然与 JavaScript 中表示数据的某些语法相同,但它并不局限于JavaScript 的范畴。**
10+
11+
# 简单值 (JSON 字符串必须使用双引号)
12+
13+
最简单的 JSON 数据形式就是简单值。
14+
15+
如下:
16+
17+
"hello word"
18+
2222222
19+
20+
上面两个都是简单的JSON;
21+
22+
23+
JavaScript字符串 与 JSON字符串的最大区别在于,JSON 字符串必须使用双引号(单引号会导致语法错误)。
24+
25+
布尔值和 null 也是有效的 JSON 形式。
26+
27+
但是,在实际应用中,JSON 更多地用来表示更复杂的数据结构,而简单值只是整个数据结构中的一部分。在接口中,用来存储键的值;
28+
29+
# 对象 (对象的属性名必须加双引号)
30+
31+
**JavaScript对象**
32+
33+
var person1 = {
34+
name: "person name",
35+
age: 29
36+
};
37+
var person2 = {
38+
"name": "person name",
39+
"age": 29
40+
};
41+
42+
上面两种方式都可以的;
43+
44+
**JSON**
45+
46+
{
47+
"name": "person name",
48+
"age": 29
49+
}
50+
51+
与 JavaScript 的对象字面量相比,JSON 对象有两个地方不一样。
52+
53+
- 1,没有声明变量(JSON 中没有变量的概念)。
54+
- 2,没有末尾的分号(因为这不是 JavaScript 语句,所以不需要分号)。
55+
56+
再说一遍,**对象的属性必须加双引号,这在 JSON 中是必需的****属性的值可以是简单值,也可以是复杂类型值**,因此可以像下面这样在对象中嵌入对象
57+
58+
{
59+
"name": "person name",
60+
"age": 29,
61+
"address": {
62+
"name":"详细地址"
63+
"city": "杭州市",
64+
"location": "文一西路XX号"
65+
}
66+
}
67+
68+
这个例子在顶级对象中嵌入了学校( "address" )信息。虽然有两个 "name" 属性,但由于它们分别属于不同的对象,因此这样完全没有问题。不过,**同一个对象中绝对不应该出现两个同名属性**
69+
70+
与 JavaScript 不同,**JSON 中对象的属性名任何时候都必须加双引号**
71+
72+
**手工编写 JSON 时,忘了给对象属性名加双引号或者把双引号写成单引号都是常见的错误。**,如果需要后台帮忙给数据的时候。假如JSON字符串不能成功转为JSON对象,原因一般都是JSON的数据格式不对;
73+
74+
# 数组
75+
76+
**JavaScript 中的数组字面量**
77+
78+
var values = [25, "hi", true];
79+
80+
**JSON中的数组**
81+
82+
[25, "hi", true]
83+
84+
> 注意,JSON 数组也没有变量和分号。
85+
86+
##### 把数组和对象结合起来,可以构成更复杂的数据集合
87+
88+
[
89+
{
90+
"title": "Professional JavaScript",
91+
"authors": [
92+
"Nicholas C. Zakas"
93+
],
94+
edition: 3,
95+
year: 2011
96+
},
97+
{
98+
"title": "Professional JavaScript",
99+
"authors": [
100+
"Nicholas C. Zakas"
101+
],
102+
edition: 2,
103+
year: 2009
104+
},
105+
{
106+
"title": "Professional Ajax",
107+
"authors": [
108+
"Nicholas C. Zakas",
109+
"Jeremy McPeak",
110+
"Joe Fawcett"
111+
],
112+
edition: 2,
113+
year: 2008
114+
},
115+
{
116+
"title": "Professional Ajax",
117+
"authors": [
118+
"Nicholas C. Zakas",
119+
"Jeremy McPeak",
120+
"Joe Fawcett"
121+
],
122+
edition: 1,
123+
year: 2007
124+
},
125+
{
126+
"title": "Professional JavaScript",
127+
"authors": [
128+
"Nicholas"
129+
],
130+
edition: 1,
131+
year: 2006
132+
}
133+
]
134+
135+
这个数组中包含一些表示图书的对象。每个对象都有几个属性,其中一个属性是 "authors" ,这个属性的值又是一个数组。对象和数组通常是 JSON 数据结构的最外层形式(当然,这不是强制规定的),利用它们能够创造出各种各样的数据结构。

JSON/readme.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
**JSON**
2+
3+
JSON(javasctipr object notation)Javascript对象表示法;
4+
5+
JSON 是 JavaScript 的一个严格的子集,利用了JavaScript中的一些模式来表示结构化数据。可以把 JSON 直接传给 eval() ,而且不必创建 DOM 对象。
6+
7+
关于 JSON,最重要的是要理解**它是一种数据格式,不是一种编程语言。虽然具有相同的语法形式,但 JSON 并不从属于 JavaScript。而且,并不是只有 JavaScript 才使用 JSON**,毕竟 JSON 只是一种数据格式。很多编程语言都有针对 JSON 的解析器和序列化器。
8+
9+
** JSON 是一个轻量级的数据格式,可以简化表示复杂数据结构的工作量。JSON 使用 JavaScript 语法的子集表示对象、数组、字符串、数值、布尔值和 null **
10+
11+
即使 XML 也能表示同样复杂的数据结果,但JSON 没有那么烦琐,而且在 JavaScript 中使用更便利。ECMAScript 5 定义了一个原生的 JSON 对象;
12+
13+
- **JSON.stringify()** 将对象序列化为 JSON 字符串;该方法接收3个参数;
14+
- **JSON.parse()** 将JSON字符串解析为JS对象(JSON对象);该方法接收2个参数;
15+
16+
这两个方法都有一些选项,通过它们可以改变过滤的方式,或者改变序列化的过程。
17+
18+
原生的 JSON 对象也得到了很多浏览器的支持,比如 IE8+、Firefox 3.5+、Safari 4+、Opera 10.5 和Chrome

JSON/解析与序列化.md

Lines changed: 222 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,222 @@
1+
**解析与序列化**
2+
3+
JSON 之所以流行,拥有与 JavaScript 类似的语法并不是全部原因,更重要的一个原因是,可以很容易把JSON 数据结构解析为有用的 JavaScript 对象
4+
5+
bookThreeTitle=books[2].title
6+
7+
下面是在 DOM结构中查找数据的代码:
8+
9+
bookThreeTitle=loadXMLDoc("books.xml").getElementsByTagName("book")[2].getAttribute("title")
10+
11+
看看这些多余的方法调用,就不难理解为什么 JSON 能得到 JavaScript 开发人员的热烈欢迎了。从s此以后,JSON 就成了 Web 服务开发中交换数据的事实标准。
12+
13+
- JSON对象
14+
- 序列化选项
15+
- 解析选项
16+
17+
# JSON对象
18+
19+
JSON 对象有两个方法: stringify() 和 parse() 。在最简单的情况下,这两个方法分别用于把JavaScript 对象序列化为 JSON 字符串和把 JSON 字符串解析为原生 JavaScript 值。
20+
21+
也可以使用JavaScript 的 eval() 函数来解析JSON字符串,但是使用 eval() 对 JSON 数据结构求值存在风险,因为可能会执行一些恶意代码。还有就是比较好性能;(eval可以解析任何字符串,属于比较底层的方法,虽然通杀但是一般不会使用;)
22+
23+
**JSON.stringify的用法**,JSON对象转为JSON字符串
24+
25+
var JSONObj = {
26+
title: "Professional JavaScript",
27+
authors: [
28+
"Nicholas C. Zakas"
29+
],
30+
edition: 3,
31+
year: 2011,
32+
testUndefined:undefined,
33+
testFunction:function(){return 2+2}
34+
};
35+
var JSONStr = JSON.stringify(JSONObj);
36+
console.log(JSONStr);//{"title":"Professional JavaScript","authors":["Nicholas C. Zakas"],"edition":3,"year":2011}
37+
console.log(typeof JSONObj);//object
38+
console.log(typeof JSONStr);//string
39+
40+
默认情况下, JSON.stringify() 输出的 JSON 字符串不包含任何空格字符或缩进,
41+
42+
在序列化 JavaScript 对象时,所有函数及原型成员都会被有意忽略,不体现在结果中。此外,值为undefined 的任何属性也都会被跳过。结果中最终都是值为有效 JSON 数据类型的实例属性。
43+
44+
上面的 **testUndefined*****testFunction** 将不会出现最终的结果中;
45+
46+
47+
**JSON.parse的用法**,JSON字符串转为JSON对象;
48+
49+
var JSONStr1 = '{title: "Professional JavaScript",authors: ["Nicholas C. Zakas"],edition: 3,year: 2011}';
50+
var JSONStr2 = '{"title": "Professional JavaScript","authors": ["Nicholas C. Zakas"],"edition": 3,year: 2011}';
51+
var JSONStr3 = '{"title": "Professional JavaScript","authors": ["Nicholas C. Zakas"],"edition": 3,"year": 2011}';
52+
var JSONStr4 = '{"title": "Professional JavaScript","authors": ["Nicholas C. Zakas"],"edition": 3,"year": 2011,"testUndefined":undefined}';
53+
54+
//var JSONObj1 = JSON.parse(JSONStr1); // 报错啦,属性值没有""
55+
//var JSONObj2 = JSON.parse(JSONStr2); // 报错啦,属性值没有全部用""
56+
var JSONObj3 = JSON.parse(JSONStr3); // 成功
57+
//var JSONObj4 = JSON.parse(JSONStr4); // 报错啦,不能含有undefined,function等数据
58+
console.log(JSONObj3);//{"title":"Professional JavaScript","authors":["Nicholas C. Zakas"],"edition":3,"year":2011}
59+
console.log(typeof JSONObj3);//object
60+
61+
> 如果传给 JSON.parse() 的字符串不是有效的 JSON,该方法会抛出错误。
62+
63+
# 序列化选项 ( JSON.stringify()的深入理解 )
64+
65+
实际上, JSON.stringify() 除了要序列化的 JavaScript 对象外,还可以接收另外两个参数,这两个参数用于指定以不同的方式序列化 JavaScript 对象。第一个参数是个过滤器,可以是一个数组,也可以是一个函数;第二个参数是一个选项,表示是否在 JSON 字符串中保留缩进。单独或组合使用这两个参数,可以更全面深入地控制 JSON 的序列化
66+
67+
JSON.stringify(jsonObj,**arguments1**,**arguments2**)
68+
69+
- arguments1 过滤器的作用,用来过滤结果;
70+
- arguments2 字符串缩进的作用;
71+
72+
##### 过滤器(用来过滤结果)
73+
74+
- **数组过滤**
75+
76+
var book={
77+
"title":"book title",
78+
authors:[
79+
"one",
80+
"two",
81+
"three"
82+
],
83+
edition:2,
84+
year:2016
85+
};
86+
var JSONStr=JSON.stringify(book,["title","year","other"]);
87+
console.log(JSONStr);//{"title":"book title","year":2016}
88+
console.log(typeof JSONStr);//string
89+
90+
JSON.stringify() 的第二个参数是一个数组,其中包含三个字符串: "title"、"year"、"other"。这两个属性与将要序列化的对象中的属性是对应的,因此在返回的结果字符串中,就只会包含这两个属性;因为源数据中没有other这个键值对;匹配不到,就会忽略掉;
91+
92+
- **函数过滤**
93+
94+
var book={
95+
"title":"book title",
96+
authors:[
97+
"one",
98+
"two",
99+
"three"
100+
],
101+
edition:2,
102+
year:2016
103+
};
104+
var JSONStr=JSON.stringify(book,function(key,value){
105+
switch (key){
106+
case "authors":
107+
return value.join("+++++");//如果键为 "authors" ,就将数组连接为一个字符串;
108+
case "year":
109+
return 5000+"change";//如果键为 "year" ,则将其值设置为 5000change ;
110+
case "edition":
111+
return undefined;//如果键为 "edition" ,通过返回 undefined 删除该属性
112+
default :
113+
return value;//最后,一定要提供 default 项,此时返回传入的值,以便其他值都能正常出现在结果中。
114+
}
115+
});
116+
console.log(JSONStr);//{"title":"book title","authors":"one+++++two+++++three","year":"5000change"}
117+
console.log(typeof JSONStr);//string
118+
119+
这里,函数过滤器根据传入的键来决定结果
120+
121+
Firefox 3.5 和 3.6 对 JSON.stringify() 的实现有一个 bug,在将函数作为该方法的第二个参数时这个 bug 就会出现,即这个函数只能作为过滤器:返回 undefined 意味着要跳过某个属性,而返回其他任何值都会在结果中包含相应的属性。Firefox 4 修复了这个 bug。(未亲自验证)
122+
123+
##### 字符串缩进
124+
125+
var book={
126+
"title":"book title",
127+
authors:[
128+
"one",
129+
"two",
130+
"three"
131+
],
132+
edition:2,
133+
year:2016
134+
};
135+
var JSONStr=JSON.stringify(book,null,4);
136+
console.log(JSONStr);
137+
console.log(typeof JSONStr);//string
138+
139+
输出的结果如下:
140+
141+
{
142+
"title": "book title",
143+
"authors": [
144+
"one",
145+
"two",
146+
"three"
147+
],
148+
"edition": 2,
149+
"year": 2016
150+
}
151+
152+
**也可以用字符替换空格**
153+
154+
var JSONStr=JSON.stringify(book,null,"- - ");
155+
156+
最终结果如下:
157+
158+
{
159+
- - "title": "book title",
160+
- - "authors": [
161+
- - - - "one",
162+
- - - - "two",
163+
- - - - "three"
164+
- - ],
165+
- - "edition": 2,
166+
- - "year": 2016
167+
}
168+
169+
JSON.stringify() 也在结果字符串中插入了换行符以提高可读性。只要传入有效的控制缩进的参数值,结果字符串就会包含换行符。最大缩进空格数为 10,所有大于 10 的值都会自动转换为 10
170+
171+
缩进字符串最长不能超过 10 个字符长。如果字符串长度超过了 10 个,结果中将只出现前 10 个字符。
172+
173+
##### toJSON() 方法
174+
175+
var book={
176+
"title":"book title",
177+
authors:[
178+
"one",
179+
"two",
180+
"three"
181+
],
182+
edition:2,
183+
year:2016,
184+
toJSON:function (){
185+
return this.title;
186+
}
187+
};
188+
var JSONStr=JSON.stringify(book);
189+
console.log(JSONStr);//"book title"
190+
console.log(typeof JSONStr);//string
191+
192+
> 可以给对象定义 toJSON() 方法,返回其自身的 JSON 数据格式。
193+
> toJSON() 可以作为函数过滤器的补充,因此理解序列化的内部顺序十分重要。
194+
195+
假设把一个对象传入 JSON.stringify() ,序列化该对象的顺序如下。
196+
- (1) 如果存在 toJSON() 方法而且能通过它取得有效的值,则调用该方法。否则,返回对象本身。
197+
- (2) 如果提供了第二个参数,应用这个函数过滤器。传入函数过滤器的值是第(1)步返回的值。
198+
- (3) 对第(2)步返回的每个值进行相应的序列化。
199+
- (4) 如果提供了第三个参数,执行相应的格式化。
200+
201+
无论是考虑定义 toJSON() 方法,还是考虑使用函数过滤器,亦或需要同时使用两者,理解这个顺序都是至关重要的。
202+
203+
# 解析选项 ( JSON.parse()的深入理解 )
204+
205+
var JSONStr = '{"title": "标题","authors": ["one","two","rhree"],"edition": 3,"year": 2016,"releaseDate": "2016,10,08 12:59:01"}';
206+
var JSONObj1 = JSON.parse(JSONStr);
207+
console.log(JSONObj1);
208+
console.log(typeof JSONObj1);//object
209+
210+
var JSONObj2 = JSON.parse(JSONStr,function(key,value){
211+
if(key === "releaseDate"){
212+
return new Date(value);
213+
}else{
214+
return value;
215+
}
216+
});
217+
console.log(JSONObj2);
218+
console.log(typeof JSONObj2);//object
219+
220+
console.log(JSONObj2.releaseDate.getFullYear()+" - "+JSONObj2.releaseDate.getMinutes());//2016 - 59
221+
222+
结果就是 JSONObj2.releaseDate 属性中会保存一个 Date 对象。正因为如此,才能基于这个对象调用getFullYear() 等方法。

0 commit comments

Comments
 (0)