JSON是JavaScript Object Notation的縮寫(xiě)芍瑞,它是一種數(shù)據(jù)交換格式左权。
在JSON出現(xiàn)之前皮胡,大家一直用XML來(lái)傳遞數(shù)據(jù)。因?yàn)閄ML是一種純文本格式赏迟,所以它適合在網(wǎng)絡(luò)上交換數(shù)據(jù)屡贺。XML本身不算復(fù)雜,但是锌杀,加上DTD甩栈、XSD、XPath抛丽、XSLT等一大堆復(fù)雜的規(guī)范以后谤职,任何正常的軟件開(kāi)發(fā)人員碰到XML都會(huì)感覺(jué)頭大了,最后大家發(fā)現(xiàn)亿鲜,即使你努力鉆研幾個(gè)月允蜈,也未必搞得清楚XML的規(guī)范。
終于蒿柳,在2002年的一天饶套,道格拉斯·克羅克福特(Douglas Crockford)同學(xué)為了拯救深陷水深火熱同時(shí)又被某幾個(gè)巨型軟件企業(yè)長(zhǎng)期愚弄的軟件工程師,發(fā)明了JSON這種超輕量級(jí)的數(shù)據(jù)交換格式垒探。
道格拉斯同學(xué)長(zhǎng)期擔(dān)任雅虎的高級(jí)架構(gòu)師妓蛮,自然鐘情于JavaScript。他設(shè)計(jì)的JSON實(shí)際上是JavaScript的一個(gè)子集圾叼。在JSON中蛤克,一共就這么幾種數(shù)據(jù)類(lèi)型:
- number:和JavaScript的
number
完全一致捺癞; - boolean:就是JavaScript的
true
或false
; - string:就是JavaScript的
string
构挤; - null:就是JavaScript的
null
髓介; - array:就是JavaScript的
Array
表示方式——[]
; - object:就是JavaScript的
{ ... }
表示方式筋现。
以及上面的任意組合唐础。
并且,JSON還定死了字符集必須是UTF-8矾飞,表示多語(yǔ)言就沒(méi)有問(wèn)題了一膨。為了統(tǒng)一解析,JSON的字符串規(guī)定必須用雙引號(hào)""
洒沦,Object的鍵也必須用雙引號(hào)""
豹绪。
由于JSON非常簡(jiǎn)單,很快就風(fēng)靡Web世界申眼,并且成為ECMA標(biāo)準(zhǔn)森篷。幾乎所有編程語(yǔ)言都有解析JSON的庫(kù),而在JavaScript中豺型,我們可以直接使用JSON,因?yàn)镴avaScript內(nèi)置了JSON的解析买乃。
把任何JavaScript對(duì)象變成JSON姻氨,就是把這個(gè)對(duì)象序列化成一個(gè)JSON格式的字符串,這樣才能夠通過(guò)網(wǎng)絡(luò)傳遞給其他計(jì)算機(jī)剪验。
如果我們收到一個(gè)JSON格式的字符串肴焊,只需要把它反序列化成一個(gè)JavaScript對(duì)象,就可以在JavaScript中直接使用這個(gè)對(duì)象了功戚。
序列化(JSON.stringify )
讓我們先把小明這個(gè)對(duì)象序列化成JSON格式的字符串:
var xiaoming = {
name: '小明',
age: 14,
gender: true,
height: 1.65,
grade: null,
'middle-school': '\"W3C\" Middle School',
skills: ['JavaScript', 'Java', 'Python', 'Lisp']
};
要輸出得好看一些娶眷,可以加上參數(shù),按縮進(jìn)輸出:
JSON.stringify(xiaoming, null, ' ');
結(jié)果:
{
"name": "小明",
"age": 14,
"gender": true,
"height": 1.65,
"grade": null,
"middle-school": "\"W3C\" Middle School",
"skills": [
"JavaScript",
"Java",
"Python",
"Lisp"
]
}
第二個(gè)參數(shù)用于控制如何篩選對(duì)象的鍵值啸臀,如果我們只想輸出指定的屬性届宠,可以傳入Array
:
JSON.stringify(xiaoming, ['name', 'skills'], ' ');
結(jié)果:
{
"name": "小明",
"skills": [
"JavaScript",
"Java",
"Python",
"Lisp"
]
}
還可以傳入一個(gè)函數(shù),這樣對(duì)象的每個(gè)鍵值對(duì)都會(huì)被函數(shù)先處理:
- 傳入函數(shù)只會(huì)返回和改變
value
,name
不會(huì)被改變
function convert(key, value) {
if (typeof value === 'string') {
return value.toUpperCase();
}
return value;
}
JSON.stringify(xiaoming, convert, ' ');
上面的代碼把所有屬性值都變成大寫(xiě):
{
"name": "小明",
"age": 14,
"gender": true,
"height": 1.65,
"grade": null,
"middle-school": "\"W3C\" MIDDLE SCHOOL",
"skills": [
"JAVASCRIPT",
"JAVA",
"PYTHON",
"LISP"
]
}
如果我們還想要精確控制如何序列化小明乘粒,可以給xiaoming
定義一個(gè)toJSON()
的方法豌注,直接返回JSON應(yīng)該序列化的數(shù)據(jù):
var xiaoming = {
name: '小明',
age: 14,
gender: true,
height: 1.65,
grade: null,
'middle-school': '\"W3C\" Middle School',
skills: ['JavaScript', 'Java', 'Python', 'Lisp'],
toJSON: function () {
return { // 只輸出name和age,并且改變了key:
'Name': this.name,
'Age': this.age
};
}
};
JSON.stringify(xiaoming); // '{"Name":"小明","Age":14}'
使用 JSON.stringify 結(jié)合 localStorage 的例子
一些時(shí)候灯萍,你想存儲(chǔ)用戶(hù)創(chuàng)建的一個(gè)對(duì)象轧铁,并且,即使在瀏覽器被關(guān)閉后仍能恢復(fù)該對(duì)象旦棉。下面的例子是 JSON.stringify 適用于這種情形的一個(gè)樣板:
// 創(chuàng)建一個(gè)示例數(shù)據(jù)
var session = {
'screens' : [],
'state' : true
};
session.screens.push({"name":"screenA", "width":450, "height":250});
session.screens.push({"name":"screenB", "width":650, "height":350});
session.screens.push({"name":"screenC", "width":750, "height":120});
session.screens.push({"name":"screenD", "width":250, "height":60});
session.screens.push({"name":"screenE", "width":390, "height":120});
session.screens.push({"name":"screenF", "width":1240, "height":650});
// 使用 JSON.stringify 轉(zhuǎn)換為 JSON 字符串
// 然后使用 localStorage 保存在 session 名稱(chēng)里
localStorage.setItem('session', JSON.stringify(session));
// 然后是如何轉(zhuǎn)換通過(guò) JSON.stringify 生成的字符串齿风,該字符串以 JSON 格式保存在 localStorage 里
var restoredSession = JSON.parse(localStorage.getItem('session'));
// 現(xiàn)在 restoredSession 包含了保存在 localStorage 里的對(duì)象
console.log(restoredSession);
反序列化(JSON.parse())
拿到一個(gè)JSON格式的字符串药薯,我們直接用JSON.parse()
把它變成一個(gè)JavaScript對(duì)象:
JSON.parse('[1,2,3,true]'); // [1, 2, 3, true]
JSON.parse('{"name":"小明","age":14}'); // Object {name: '小明', age: 14}
JSON.parse('true'); // true
JSON.parse('123.45'); // 123.45
JSON.parse()
還可以接收一個(gè)函數(shù),用來(lái)轉(zhuǎn)換解析出的屬性:
- 遍歷順序 : 遍歷順序是平級(jí)沒(méi)內(nèi)部屬性,先平級(jí),從內(nèi)向外的