JSON

曾經(jīng)有一段時間,XML是互聯(lián)網(wǎng)上傳輸結(jié)構(gòu)化數(shù)據(jù)的事實(shí)標(biāo)準(zhǔn)。
JSON是JavaScript的一個嚴(yán)格的子集苔严,利用了JavaScript中的一些模式來表示結(jié)構(gòu)化數(shù)據(jù)甩恼。

語法


JSON語法可以表示一下三種類型的值:

  • 簡單值:使用與JavaScript相同的語法蟀瞧,可以在JSON中表示字符串、數(shù)值媳拴、布爾值和null黄橘。但JSON不支持JavaScript中的特殊值undefined。
  • 對象:對象作為一種復(fù)雜數(shù)據(jù)類型屈溉,表示的是一組有序的鍵值對塞关。而每個鍵值對中的值可以是簡單值,也可以是復(fù)雜數(shù)據(jù)類型的值子巾。
  • 數(shù)組:數(shù)組也是一種復(fù)雜數(shù)據(jù)類型帆赢⌒⊙梗可以通過數(shù)值索引來訪問其中的值。數(shù)值的值也可以是任意類型椰于。

簡單值

JavaScript字符串與JSON字符串的最大區(qū)別在于怠益,JSON字符串必須使用雙引號(單引號會導(dǎo)致語法錯誤)。
布爾值和null也是有效的JSON形式瘾婿。

對象

與JavaScript的對象字面量相比蜻牢,JSON對象有兩個不同的地方。首先偏陪,沒有聲明變量抢呆。其次,沒有末尾的分好笛谦。對象的屬性必須加雙引號抱虐。

同一個對象中絕對不應(yīng)該出現(xiàn)兩個同名屬性搓侄。

與JavaScript不同逞刷,JSON中對象的屬性名任何時候都必須加雙引號。

數(shù)組

同樣颂砸,JSON數(shù)組也沒有變量和分號灶轰。

解析與序列化


JSON數(shù)據(jù)結(jié)構(gòu)可以解析為JavaScript對象谣沸。與XML數(shù)據(jù)結(jié)構(gòu)要解析成DOM文檔而且從中提取數(shù)據(jù)極為麻煩,JSON可以解析為JavaScript對象的優(yōu)勢極為明顯框往。

JSON對象

早起的JSON解析器基本上就是使用JavaScript的eval()函數(shù)鳄抒。
ECMAScript 5對解析JSON的行為進(jìn)行規(guī)范,定義了全局對象JSON椰弊。支持這個對象的瀏覽器有IE8+许溅、Firefox3.5+、Safari 4+秉版、Chrome和Opera 10.5+贤重。對于較早版本的瀏覽器,可以使用一個shim:https://github.com/douglascrockford/JSON-js清焕。在舊版本的瀏覽器中并蝗,使用eval()對JSON數(shù)據(jù)結(jié)構(gòu)求值存在風(fēng)險,因為可能會執(zhí)行一些惡意代碼秸妥。

JSON對象有兩個方法:stringify()parse()滚停。
在最簡單的情況下,這兩個方法分別用于把JavaScript對象序列化為JSON字符串和把JSON字符串解析為原生JavaScript值粥惧。

默認(rèn)情況下键畴,JSON.stringify()輸出的JSON字符串不包括任何空格字符或縮進(jìn)。
在序列化JavaScript對象時,所有函數(shù)及原型成員都會被有意忽略起惕,不體現(xiàn)在結(jié)果中涡贱。此外,值為undefined的任何屬性都會被跳過惹想。

如果傳遞給JSON.parse()的字符串不是有效的JSON问词,該方法會拋出錯誤。

序列化選項

JSON.stringify()還可以接受另外兩個參數(shù)嘀粱。第一個參數(shù)是個過濾器激挪,可以是一個數(shù)組,也可以是一個函數(shù)草穆;第二個參數(shù)是一個選項灌灾,表示是否在JSON字符串中保留縮進(jìn)。

過濾結(jié)果
如果過濾器參數(shù)是一個數(shù)組悲柱,那么JSON.stringify()的結(jié)果中將只包含數(shù)組中列出的屬性。

如果第二個參數(shù)是一個函數(shù)些己,傳入的函數(shù)接受兩個參數(shù)豌鸡,屬性(鍵)名和屬性值。根據(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(bool, function (key, value) {
    switch (key) {
        case "authors":
            return value.join(",");

        case "year":
            return 5000;

        case "edition":
            return undefined;

        default:
            return value;
    }
});

Firefox3.5和3.6對JSON.stringify()的實(shí)現(xiàn)有一個bug璧南,在將函數(shù)作為該方法的第二個參數(shù)時這個bug 會出現(xiàn)掌逛,即這個函數(shù)只能作為過濾器:返回undefined意味著要跳過某個屬性,而返回其他任何值都會在結(jié)果中包含相應(yīng)的屬性司倚。Firefox4修復(fù)了這個bug豆混。

字符串縮進(jìn)
JSON.stringify()方法的第三個參數(shù)用于控制結(jié)果中的縮進(jìn)和空白符。如果這個參數(shù)是一個數(shù)值动知,那它表示的是每個級別縮進(jìn)的空格數(shù)皿伺。
只要傳入有效的控制縮進(jìn)的參數(shù)值,結(jié)果字符串就會包含換行符盒粮。最大縮進(jìn)空格數(shù)為10鸵鸥,所有大于10的值都會自動轉(zhuǎn)換為10。

如果縮進(jìn)參數(shù)是一個字符串而非數(shù)值拆讯,則這個字符串將在JSON字符串中被用作縮進(jìn)字符(不再使用空格)脂男。在使用字符串的情況下养叛,可以將縮進(jìn)設(shè)置為制表符,或者兩個短劃線之類的任意字符宰翅∑縮進(jìn)字符串最長不能超過10個字符長。如果字符串長度超過了10個汁讼,結(jié)果中將只出現(xiàn)前10個字符淆攻。

toJSON()方法
有時候,JSON.stringify()還是不能滿足對某些對象進(jìn)行自定義序列化的需求嘿架。在這些情況下瓶珊,可以通過對象上調(diào)用toJSON()方法,返回其自身的JSON數(shù)據(jù)格式耸彪。

var book = {
    "title": "Professional JavaScript",
    "authors": ["Nicholas C. Zakas"
    ],
    edition: 3,
    year: 2011,
    toJSON: function () {
        return this.title;
    }
};
var jsonText = JSON.stringify(book);

這個對象也將被序列化為一個簡單的字符串而非對象伞芹。可以讓toJSON()方法返回任何序列化的值蝉娜,它都能正常工作唱较。也可以讓這個方法返回undefined,此時如果包含它的對象嵌入在另一個對象中召川,會導(dǎo)致該對象的值變成null南缓,而如果包含它的對象是頂級對象,結(jié)果就是undefined荧呐。

toJSON()可以作為函數(shù)過濾器的補(bǔ)充汉形,因此理解序列化的內(nèi)部順序十分重要。假設(shè)把一個對象傳入JSON.stringify()倍阐,序列化該對象的順序如下概疆。

  1. 如果存在toJSON()方法而且能通過它取得有效的值,則調(diào)用方法收捣。否則届案,按默認(rèn)順序執(zhí)行序列化。
  2. 如果提供了第二個參數(shù)罢艾,應(yīng)用這個函數(shù)過濾器楣颠。傳入函數(shù)過濾器的值是第一步返回的值。
  3. 對第二步返回的每個值進(jìn)行相應(yīng)的序列化咐蚯。
  4. 如果提供了第二個參數(shù)童漩,執(zhí)行相應(yīng)的格式化。

解析選項

JSON.parse()方法也可以接受另一個參數(shù)春锋,該參數(shù)是一個函數(shù)矫膨,將在每個鍵值對上調(diào)用。這個函數(shù)接受兩個參數(shù),一個鍵和一個值侧馅,并返回一個值危尿。

如果函數(shù)返回undefined,則表示要從結(jié)果中刪除相應(yīng)的鍵馁痴;如果返回其他值谊娇,則將該值插入到結(jié)果中。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末罗晕,一起剝皮案震驚了整個濱河市济欢,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌小渊,老刑警劉巖法褥,帶你破解...
    沈念sama閱讀 211,290評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異酬屉,居然都是意外死亡半等,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,107評論 2 385
  • 文/潘曉璐 我一進(jìn)店門梆惯,熙熙樓的掌柜王于貴愁眉苦臉地迎上來酱鸭,“玉大人,你說我怎么就攤上這事垛吗。” “怎么了烁登?”我有些...
    開封第一講書人閱讀 156,872評論 0 347
  • 文/不壞的土叔 我叫張陵怯屉,是天一觀的道長。 經(jīng)常有香客問我饵沧,道長锨络,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,415評論 1 283
  • 正文 為了忘掉前任狼牺,我火速辦了婚禮羡儿,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘是钥。我一直安慰自己掠归,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,453評論 6 385
  • 文/花漫 我一把揭開白布悄泥。 她就那樣靜靜地躺著虏冻,像睡著了一般。 火紅的嫁衣襯著肌膚如雪弹囚。 梳的紋絲不亂的頭發(fā)上厨相,一...
    開封第一講書人閱讀 49,784評論 1 290
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼蛮穿。 笑死庶骄,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的践磅。 我是一名探鬼主播单刁,決...
    沈念sama閱讀 38,927評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼音诈!你這毒婦竟也來了幻碱?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,691評論 0 266
  • 序言:老撾萬榮一對情侶失蹤细溅,失蹤者是張志新(化名)和其女友劉穎褥傍,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體喇聊,經(jīng)...
    沈念sama閱讀 44,137評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡恍风,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,472評論 2 326
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了誓篱。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片朋贬。...
    茶點(diǎn)故事閱讀 38,622評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖窜骄,靈堂內(nèi)的尸體忽然破棺而出锦募,到底是詐尸還是另有隱情,我是刑警寧澤邻遏,帶...
    沈念sama閱讀 34,289評論 4 329
  • 正文 年R本政府宣布糠亩,位于F島的核電站,受9級特大地震影響准验,放射性物質(zhì)發(fā)生泄漏赎线。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,887評論 3 312
  • 文/蒙蒙 一糊饱、第九天 我趴在偏房一處隱蔽的房頂上張望垂寥。 院中可真熱鬧,春花似錦另锋、人聲如沸滞项。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,741評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽蓖扑。三九已至,卻和暖如春台舱,著一層夾襖步出監(jiān)牢的瞬間律杠,已是汗流浹背潭流。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留柜去,地道東北人灰嫉。 一個月前我還...
    沈念sama閱讀 46,316評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像嗓奢,于是被迫代替她去往敵國和親讼撒。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,490評論 2 348

推薦閱讀更多精彩內(nèi)容