json的應(yīng)用早在2001年就已經(jīng)開始了,JSON是JavaScript的一個嚴格的子集,利用JavaScript中的一些模式來表示結(jié)構(gòu)化數(shù)據(jù)。JSON是一種數(shù)據(jù)格式,不是一種編程語言,雖然具有相同的語法形式,但JSON并不從屬于JavaScript。
一、語法
json的語法可以表示一下三種類型的值
- 簡單值:可以在JSON中表示字符串、數(shù)值、布爾值和null,但JSON不支持JavaScript中的特殊值undefined
- 對象
- 數(shù)組
例如:json數(shù)據(jù)格式
{
"name":"anxiaoyan",
"age":22,
"school":{
"name":"NWAFU",
"location":"shanxi·china"
},
"hobby":[
"reading",
"game",
"sports"
]
}
二、Json解析和序列化
JSON之所以流行,擁有與JavaScript類似的語法并不是全部的原因。更重要的一個原因是,可以把JSON數(shù)據(jù)結(jié)構(gòu)解析為有用的JavaScript對象。
JSON對象有兩個方法:stringify()和parse(),這兩個方法分別用于將JavaScript對象序列化成json字符串和把json字符串解析為原生的JavaScript值。
2.1JavaScript序列化成json字符串
例如:
var book = {
title:"Professional javascript",
authors:[
"Nicholas C.Zakas"
],
edition:3,
year:2011
};
var jsonText = JSON.stringify(book);
結(jié)果顯示保存在jsonText中的字符串的格式如下所示:
{"title":"Professional javascript","authors":["Nicholas C.Zakas"],"edition":3,"year":2011}
注意:在序列化JavaScript對象時,所有函數(shù)及原型成員都會被有意忽略,不體現(xiàn)在結(jié)果中,,此外值為undefined的任何屬性也都會被跳過,結(jié)果最終都是值為有效的json數(shù)據(jù)類型的實例屬性。
2.2Json字符串解析為JavaScript對象
將JSON字符串直接傳遞給JSON.parse()就可以得到相應(yīng)的JavaScript值
var bookCopy = JSON.parse(jsonText);
返回結(jié)果與book具有相同的屬性,但是他們是兩個相互獨立的,沒有任何關(guān)系的對象。
如果傳給JSON.parse()的字符串不是有效的json,該方法就會拋出錯誤
2.3序列化選項
JSON.stringify()除了要序列化的JavaScript對象之外,它還可接收另外兩個參數(shù),這兩個參數(shù)用于指定以不同方式序列化JavaScript對象,第一個參數(shù)是個過濾器,可以是一個數(shù)據(jù),也可以是一個函數(shù)。第二個參數(shù)是一個選項,表示是否在JSON字符串中保留縮進,單獨或組合使用這兩個參數(shù),可以更加全面的控制JSON的序列化。
2.3.1過濾結(jié)果
- 如果過濾參數(shù)是個數(shù)組,那么JSON.stringify()的結(jié)果中只包含數(shù)組中列出的屬性。例如:
var book = {
title:"Professional javascript",
authors:[
"Nicholas C.Zakas"
],
edition:3,
year:2011
};
var jsonText = JSON.stringify(book,["title","edition"]);
console.log(jsonText);
JSON.stringify()第二個參數(shù)是一個數(shù)組,其中包含“title”和“edition”,這兩個屬性將要序列化的對象中的屬性是對應(yīng)的,因此在返回結(jié)果中,只包含這兩個屬性
{"title":"Professional javascript","edition":3}
- 如果第二個參數(shù)是一個函數(shù),傳入的函數(shù)接收兩個參數(shù),key和value,根據(jù)屬性鍵名可以知道應(yīng)該如何處理要序列化的對象中的屬性,屬性名只能是字符串,而在值并非鍵值對結(jié)構(gòu)的值時,鍵名可以是空字符串,為了改變序列化對象的結(jié)果,函數(shù)返回的值就是相應(yīng)鍵的值,不過注意,如果函數(shù)返回了undefined,那么相應(yīng)的屬性會被忽略。例如:
var book = {
title:"Professional javascript",
authors:[
"Nicholas C.Zakas"
],
edition:3,
year:2011
};
var jsonText = JSON.stringify(book,function(key,value){
switch(key){
case "authors":
return value.join(",");
case "year":
return 5000;
case "edition":
return undefined;
default:
return value;
}
});
console.log(jsonText);
如果鍵為authors,就將數(shù)組連接為一個字符串,如果鍵為“year”,將其值設(shè)為5000,如果鍵為“edition”,通過返回undefined刪除該屬性。
序列化之后的JSON字符串為
{"title":"Professional javascript","authors":"Nicholas C.Zakas","year":5000}
2.4字符串縮進
JSON.stringify()的第三個參數(shù)用于控制結(jié)果中的縮進和空白符.
- 如果這個參數(shù)是一個數(shù)值,那它表示的是每個級別縮進的空格數(shù),例如:要求每個級別縮進四個空格,代碼如下:
var jsonText = JSON.stringify(book,null,4)
保存在jsonText中的字符串如下所示:
{
"title": "Professional javascript",
"authors": [
"Nicholas C.Zakas"
],
"edition": 3,
"year": 2011
}
- 如果縮進參數(shù)是一個字符串而非數(shù)值,則這個字符串將在json字符串中被用作縮進字符(不再使用空格),例如:
var jsonText = JSON.stringify(book,null,"- -");
這樣,jsonText中的字符串將變成如下所示:
{
- -"title": "Professional javascript",
- -"authors": [
- -- -"Nicholas C.Zakas"
- -],
- -"edition": 3,
- -"year": 2011
}
注意:縮進字符串最長不能超過10個字符,如果字符串長度超過了10個,結(jié)果中將只出現(xiàn)前10個字符
2.4 toJSON()方法
有時候,JSON.stringify()還是不能滿足對某些對象進行自定義序列化的需求,在這些情況下可以對象定義toJSON()方法,返回其自身的JSON數(shù)據(jù)格式??梢詾槿魏螌ο筇砑觮oJSON()方法,例如:
var book = {
title:"Professional javascript",
authors:[
"Nicholas C.Zakas"
],
edition:3,
year:2011,
toJSON:function(){
return this.title;
}
};
var jsonText = JSON.stringify(book);
以上book對象定義了toJSON()方法,所以JSON.stringify()返回結(jié)果如下:
"Professional javascript"
注意:當toJSON()方法返回undefined,此時如果包含它的對象嵌入在另外一個對象,會導致它的值變?yōu)閚ull,如果它是頂級對象,結(jié)果就是undefined。
toJSON()可以作為函數(shù)過濾器的補充,因此理解序列化的內(nèi)部順序十分重要。假設(shè)把一個對象傳入JSON.stringify()序列化該對象的順序如下:
(1) 如果存在toJSON()方法而且能通過它取得有效的值,則調(diào)用該方法。否則,返回對象本身。
(2)如果提供了第二個參數(shù),應(yīng)用這個函數(shù)過濾器。傳入函數(shù)過濾器的值是第(1)步返回的值
(3)對第(2)步返回的每個值進行相應(yīng)的序列化
(4)如果提供了第三個參數(shù),執(zhí)行相應(yīng)的格式化。