本文輸出和JSON有關(guān)的以下內(nèi)容
? JSON和javaScript
? JSON的語法介紹
? JSON的數(shù)據(jù)類型
? JSON和XMLHTTPRequest
? JSON的序列化和反序列化處理
1.1 JSON和javaScript
JSON是一種數(shù)據(jù)交換格式。
JSON的全稱是JavaScript Object Notation,翻譯為JavaScript對象表示法。JSON的這個全稱,無疑讓很多人既興奮又困惑,興奮的人直接認(rèn)為這就是JavaScript中的對象,困惑的人覺察出JSON數(shù)據(jù)和JavaScript對象好像有些不一樣。接下來我們先談一談JSON數(shù)據(jù)和JavaScript的關(guān)系。
誠然,從JSON的全稱可以看出JSON和JavaScript語言必定有種某種神秘關(guān)聯(lián),至少能夠確定的是JSON的命名確實來源于JavaScript這門語言。
JSON基于JavaScript對象字面量,但JSON本身是一種數(shù)據(jù)交換格式,因此它是獨立于語言的。JSON全稱為JavaScript對象表示法,在理解的時候可以認(rèn)為JSON ==> JavaScript && 對象 && 表示法
JavaScript我們知道是一門動態(tài)腳本語言,那么對象表示法是什么?
對象是面向?qū)ο缶幊陶Z言中一種常見的數(shù)據(jù)類型,表示鍵值對的集合,那么表示法是什么?
表示法:是指一個可以表示諸如數(shù)字或單詞等數(shù)據(jù)的字符系統(tǒng)。
JSON起源于JavaScript(靈感來源于JavaScript的對象語法),但真正重要的是具體的表示法本身。JSON不僅獨立于語言,而且使用了一種在許多編程語言中能夠找到共同元素的表達方式?;谶@種簡潔的表達方式,JSON迅速成為一種流行的數(shù)據(jù)交換格式。目前,客戶端和服務(wù)器端在進行數(shù)據(jù)通信的時候,常見的數(shù)據(jù)格式就是JSON和XML。
1.2 JSON的語法介紹
1.2.1 JSON的語法
JSON因為基于JavaScript的字面量,所以我們先來看下JavaScript字面量的樣子,下面給出簡單的代碼示例,描述了一個書對象。
var book = {
name:"聲名狼藉者的生活",
price:42.00,
author:"福柯",
press:"北京大學(xué)出版社",
read:function () {
console.log("我的書名為:聲名狼藉者的的生活,作者為???...");
}
};
順便貼出一個簡短的JSON數(shù)據(jù)
{
"name":"聲名狼藉者的生活",
"price":42.00,
"author":"福柯",
"press":"北京大學(xué)出版社",
"content":["a","b","c",123]
}
我們可以對比下上面的JavaScript對象和JSON數(shù)據(jù),會發(fā)現(xiàn)它們的結(jié)構(gòu)和語法形式很像,都是鍵值對的集合,接下來我們做更詳細(xì)的說明。JSON數(shù)據(jù)在表達上和對象保持一致,但因為數(shù)據(jù)交換格式的核心是數(shù)據(jù),所以JSON并不會保存函數(shù)等信息。JSON數(shù)據(jù)所基于的JavaScript對象字面量單純指對象字面量以及其屬性的語法表示。
JSON的主要語法特點
① 以鍵值對的方式來保存數(shù)據(jù)
② 標(biāo)準(zhǔn)的JSON數(shù)據(jù)的key必須要使用雙引號包裹
③ { } 用于表示和存放對象,[ ] 用于表示和存放數(shù)組數(shù)據(jù)
JSON數(shù)據(jù)的讀取,在讀取JSON的時候
{ 表示開始讀取對象,} 表示對象讀取結(jié)束
[ 表示開始讀取數(shù)組,] 表示數(shù)組讀取結(jié)束
:用于分隔鍵值對中的key和value
, 用于分隔對象中的多個鍵值對或者是數(shù)組中的多個元素
JavaScript對象字面量中的key可以使用單引號,可以使用雙引號,可以不必加上引號包裹,但是在JSON中,所有的key必須要加上雙引號。
1.2.2 JSON的驗證和格式化工具
下面列出一些能夠?qū)SON數(shù)據(jù)進行校驗和格式化的在線地址
https://jsonlint.com/
http://tool.oschina.net/codeformat/json
https://jsonformatter.curiousconcept.com/
1.2.3 JSON文件和MIME類型
在開發(fā)中我們經(jīng)常需要處理大量的JSON數(shù)據(jù),JSON這種數(shù)據(jù)交換格式可以作為獨立的文件存在于文件系統(tǒng)中,文件擴展名為 .json
JSON的MIME類型是application/json, 詳細(xì)信息請參考IANA官網(wǎng)維護的所有媒體類型列表。
1.3 JSON的數(shù)據(jù)類型
JSON中(作為value值)的數(shù)據(jù)類型包括對象、字符串、數(shù)字、布爾值、null和數(shù)組六種。
① 字符串
JSON中的字符串可以由任何的Unicode字符構(gòu)成,字符串的兩邊必須被雙引號包裹。需要注意的是:雖然在JavaScript語言中字符串可以使用單引號來包裹,但是在JSON中的字符串必須使用雙引號包裹。
如果字符串中存在以下特殊字符,那么需要在它們的前面加上一個反斜線(\)來進行轉(zhuǎn)義。
- " 雙引號
- \ 反斜線
- \/ 正斜線
- \b 退格符
- \f 換頁符
- \t 制表符
- \n 換行符
- \r 回車符
- \u 后面跟16進制字符
② 數(shù)字
JSON中的數(shù)字可以是整數(shù)、小數(shù)、負(fù)數(shù)或者是指數(shù)。
③ 布爾類型
JSON數(shù)據(jù)僅僅支持小寫形式的布爾類型值:true 和 false。
④ null類型
JSON中沒有undefined這種數(shù)據(jù)類型,它使用null表示空,并且必須小寫。
在JavaScript語言中,var obj = null 表示把obj這個對象清空,它和undefined不太一樣,null表示什么都沒有,undefined表示未定義。
⑤ 對象類型
對象類型是使用逗號分隔的鍵值對的集合,使用大括號({})裹。
⑥ 數(shù)組類型
數(shù)組類型是元素的集合,每個元素都可以是字符串、數(shù)字、布爾值、對象或者數(shù)組中的任何一種。元素與元素之間使用逗號隔開,所有的元素被方括號([])包裹,建議數(shù)組中所有的元素都應(yīng)該是相同數(shù)據(jù)類型的。
1.4 JSON和XMLHTTPRequest
在前端開發(fā)中有一種發(fā)送網(wǎng)絡(luò)請求的技術(shù)Ajax,它可以實現(xiàn)異步處理網(wǎng)絡(luò)通信而不刷新頁面。
Ajax的全稱為Asynchronous JavaScript and XML,即異步的JavaScript和XML。我們知道JSON的定位是輕量級的數(shù)據(jù)交互格式,客戶端在和服務(wù)器端進行網(wǎng)絡(luò)通信的時候,服務(wù)器端返回給我們的數(shù)據(jù)大多數(shù)是JSON或者是XML。也就是說JSON數(shù)據(jù)在Ajax網(wǎng)絡(luò)通信中可能扮演重要的角色,那什么Ajax不叫異步的JSON而叫做異步的XML呢? 答案是:因為剛提出這種網(wǎng)絡(luò)請求技術(shù)的時候,XML相比JSON更流行。
在Ajax網(wǎng)絡(luò)請求中用到的核心對象XMLHTTPRequest也是如此,其實這個對象命名中包含XML也僅僅是因為對于當(dāng)時而言,XML是網(wǎng)絡(luò)請求中最常用的數(shù)據(jù)交換格式。如果放在今天,那么它們的名字應(yīng)該叫做AjaJ(Asynchronous JavaScript and JSON)和JSONHTTPRequest更合適一些。
1.5 JavaScript中JSON數(shù)據(jù)的序列化和反序列化處理
在網(wǎng)絡(luò)請求中,如果服務(wù)器返回給我們的數(shù)據(jù)是JSON數(shù)據(jù),那么為了方便對數(shù)據(jù)的操作,通常我們在網(wǎng)絡(luò)請求成功拿到JSON數(shù)據(jù)之后會先對JSON數(shù)據(jù)進行反序列化操作。
在前端開發(fā)中,早期的JSON解析基本上由eval函數(shù)來完成,ECMAScript5對解析JSON的行為進行了規(guī)范,定義了全局對象JSON。目前IE8+、FireFox 3.5+、Opera 10.5、Safari 4+和Chrome等瀏覽器均支持原生的JSON全局對象。
JSON數(shù)據(jù)的處理主要涉及到兩方面:序列化處理和反序列化處理
1.5.1 使用eavl函數(shù)來處理JSON數(shù)據(jù)
eavl函數(shù)說明
JavaScript語言中eavl函數(shù)可以把字符串轉(zhuǎn)換為js的代碼并且馬上執(zhí)行,使用情況和Function構(gòu)造函數(shù)用法類型。
eval("var a = 123;");
console.log(a + 1); //輸出結(jié)果為124
因為從某種程度上來講,json其實是JavaScript語言的嚴(yán)格子集,所以我們可以直接通過eval函數(shù)來對json數(shù)據(jù)進行解析。需要注意的是,使用eavl函數(shù)來對json數(shù)據(jù)結(jié)構(gòu)求值存在風(fēng)險,因為可能會執(zhí)行一些惡意代碼。
eavl函數(shù)解析JSON
服務(wù)器返回給前端的json數(shù)據(jù)可能是{...}形式的,也可能是[...]形式的,分別對應(yīng)js中的對象和數(shù)組。如果是{...}形式的,那么在解析的時候,如果直接以eval(json)的方式處理會報錯,因為js中不允許直接寫{name:"zs"}類似的語句。遇到這種結(jié)構(gòu)的json數(shù)據(jù),通常我們有兩種方式進行處理:① 包裝成表達式 ② 賦值給變量。
//001 [...] 格式的json數(shù)據(jù)
var arrJson= '[{"name":"zs","age":18},{"name":"lisi","age":28}]';
var jsonArr = eval(arrJson);
//002 {...} 格式的json數(shù)據(jù)
var objJson = `{"name":"wendingding","age":18,"contentAbout":["JavaScript","CSS","HTML"],"car":{"number":"粵A6666","color":"red"}}`;
//eval(json); 錯誤的演示:報錯
//處理方式(1):以拼接的方式賦值給變量
eval("var jsonObj1 = " + objJson);
//處理方式(2):包裝成表達式
var jsonObj2 = eval("(" + objJson +")");
//打印轉(zhuǎn)換后得到的數(shù)組|對象
console.log(jsonArr);
console.log(jsonObj1);
console.log(jsonObj2);

1.5.2 使用JSON全局對象來處理JSON數(shù)據(jù)
JSON全局對象擁有兩個方法:stringify()和parse(),其中parse方法用于把json數(shù)據(jù)反序列化為原生的js,stringify方法用于把js對象序列化為json字符串。
parse方法的使用
語法:JSON.parse(jsonString,[fn])
參數(shù)說明
第一個參數(shù):jsonString為要解析的json字符串
第二個參數(shù):fn是一個可選參數(shù),該參數(shù)為函數(shù)類型,接收兩個參數(shù),分別是每個鍵值對的key和value。
//json字符串
var objJson = `{"name":"wendingding","age":18,"contentAbout":["JavaScript","CSS","HTML"],"car":{"number":"粵A6666","color":"red"}}`;
//把json字符串轉(zhuǎn)換為js數(shù)組
var arrJson= '[{"name":"zs","age":18},{"name":"lisi","age":28}]';
//把json字符串轉(zhuǎn)換為js對象
var jsonObj = JSON.parse(objJson);
var jsonArr = JSON.parse(arrJson);
console.log(jsonObj);
console.log(jsonArr);
//演示parse方法中函數(shù)參數(shù)的使用
function fn(key, value) {
if (key === "name") {
return value + "++" //在原有value值的基礎(chǔ)上拼接++字符串
} else if (key === "age") {
return undefined //如果返回undefined,則表示刪除對應(yīng)的鍵值對
} else {
return value //正常返回對應(yīng)的value值
}
}
console.log(JSON.parse(objJson, fn));

stringify方法使用說明
語法:JSON.stringify(Obj,[fn|arr],[space])
參數(shù)說明
第一個參數(shù):Obj為要進行序列化操作的JavaScript對象
第二個參數(shù):過濾器,可以是函數(shù)或者是一個數(shù)組
第三個參數(shù):是否在生成的json字符串中保留縮進,用于控制縮進的字符
//js中的普通對象
var obj = {
name:"zs",
age:18,
friends:["小霸王","花仙子","奧特曼"],
other:undefined,
showName:function () {
console.log(this.name);
}
};
//把js中的對象轉(zhuǎn)換為json字符串
//注意:
//001 如果鍵值對中存在value值為undefined的數(shù)據(jù),那么會被跳過
//002 對象中的方法以及該對象的原型成員數(shù)據(jù)在進行轉(zhuǎn)換的時候,會被有意忽略
console.log(JSON.stringify(obj));
//控制縮進,該參數(shù)的值可以是數(shù)字也可以是字符串,自動換行
//001 如果是字符串那么會把對應(yīng)的字符拼接在鍵值對前面,超過10個字符的省略
//002 如果是數(shù)字那么會設(shè)置對應(yīng)的縮進,最多為10,超過則默認(rèn)為10
console.log(JSON.stringify(obj, null, 4));
console.log(JSON.stringify(obj, null, "@@"));
//過濾器(數(shù)組):表示只處理key為name和age這兩個鍵值對
console.log(JSON.stringify(obj, ["name","age"]));
//過濾器(函數(shù)):
function fn(key,value) {
if (key === "age")
{
return value + 20;
}else if (key === "name")
{
return undefined; //過濾掉key為name這個鍵值對
}else
{
return value;
}
}
console.log(JSON.stringify(obj,fn));

JSON數(shù)據(jù)總結(jié)
? JSON全稱是JavaScript Object Notation基于JavaScript,是JavaScript的子集。
? JSON雖然是JavaScript的子集,但并不從屬于JavaScript,它獨立于語言。
? JSON是用來表示和傳輸數(shù)據(jù)的格式,比XML更輕量級,現(xiàn)已成為web數(shù)據(jù)交換的事實標(biāo)準(zhǔn)。
? JSON的優(yōu)勢在于其可以方便的把JSON字符串?dāng)?shù)據(jù)轉(zhuǎn)換為對應(yīng)的對象,比XML更方便且數(shù)據(jù)更小。
? JSON語法可以表示:字符串、數(shù)值、布爾值、null、對象和數(shù)組6種類型的值,不支持undefined。
? JSON中的"鍵"區(qū)別于JavaScript,必須要加上雙引號。
? JSON解析可以使用傳統(tǒng)的eval函數(shù),或ECMAScript5推出的全局對象來處理。
參考資料
JSON官網(wǎng):http://json.org/
JSON維基百科:https://en.wikipedia.org/wiki/JSON
JSON作者簡介:https://en.wikipedia.org/wiki/Douglas_Crockford
JSON必知必會:https://book.douban.com/subject/26789960/
JavaScript高級程序設(shè)計:https://book.douban.com/subject/10546125/
