JSON對象

JSON 格式

JSON 格式(JavaScript Object Notation 的縮寫)是一種用于數(shù)據(jù)交換的文本格式,2001年由 Douglas Crockford 提出挽霉,目的是取代繁瑣笨重的 XML 格式。

相比 XML 格式悼院,JSON 格式有兩個顯著的優(yōu)點:書寫簡單,一目了然咒循;符合 JavaScript 原生語法据途,可以由解釋引擎直接處理,不用另外添加解析代碼叙甸。所以颖医,JSON迅速被接受,已經(jīng)成為各大網(wǎng)站交換數(shù)據(jù)的標準格式裆蒸,并被寫入ECMAScript 5熔萧,成為標準的一部分。

簡單說光戈,每個 JSON 對象,就是一個值遂赠。要么是簡單類型的值久妆,要么是復合類型的值,但是只能是一個值跷睦,不能是兩個或更多的值筷弦。這就是說,每個 JSON 文檔只能包含一個值抑诸。

JSON 對值的類型和格式有嚴格的規(guī)定烂琴。

  1. 復合類型的值只能是數(shù)組或?qū)ο螅荒苁呛瘮?shù)蜕乡、正則表達式對象奸绷、日期對象。
  1. 簡單類型的值只有四種:字符串层玲、數(shù)值(必須以十進制表示)号醉、布爾值和null(不能使用NaN, Infinity, -Infinityundefined)反症。
  1. 字符串必須使用雙引號表示,不能使用單引號畔派。
  1. 對象的鍵名必須放在雙引號里面铅碍。
  1. 數(shù)組或?qū)ο笞詈笠粋€成員的后面,不能加逗號线椰。

以下是合格的 JSON 值胞谈。

["one", "two", "three"]

{ "one": 1, "two": 2, "three": 3 }

{"names": ["張三", "李四"] }

[ { "name": "張三"}, {"name": "李四"} ]

以下是不合格的 JSON 值。

{ name: "張三", 'age': 32 }  // 屬性名必須使用雙引號

[32, 64, 128, 0xFFF] // 不能使用十六進制值

{ "name": "張三", "age": undefined } // 不能使用undefined

{ "name": "張三",
  "birthday": new Date('Fri, 26 Aug 2011 07:13:10 GMT'),
  "getName": function() {
      return this.name;
  }
} // 不能使用函數(shù)和日期對象

需要注意的是憨愉,空數(shù)組和空對象都是合格的 JSON 值烦绳,null本身也是一個合格的 JSON 值。

ES5 新增了JSON對象莱衩,用來處理 JSON 格式數(shù)據(jù)爵嗅。它有兩個方法:JSON.stringify()JSON.parse()

JSON.stringify()

基本用法

JSON.stringify方法用于將一個值轉為字符串笨蚁。該字符串符合 JSON 格式睹晒,并且可以被JSON.parse方法還原。

JSON.stringify('abc') // ""abc""
JSON.stringify(1) // "1"
JSON.stringify(false) // "false"
JSON.stringify([]) // "[]"
JSON.stringify({}) // "{}"

JSON.stringify([1, "false", false])
// '[1,"false",false]'

JSON.stringify({ name: "張三" })
// '{"name":"張三"}'

上面代碼將各種類型的值括细,轉成 JSON 字符串伪很。

需要注意的是,對于原始類型的字符串奋单,轉換結果會帶雙引號锉试。

JSON.stringify('foo') === "foo" // false
JSON.stringify('foo') === "\"foo\"" // true

上面代碼中,字符串foo览濒,被轉成了""foo""呆盖。這是因為將來還原的時候,雙引號可以讓 JavaScript 引擎知道贷笛,foo是一個字符串应又,而不是一個變量名。

如果原始對象中乏苦,有一個成員的值是undefined株扛、函數(shù)或 XML 對象,這個成員會被過濾汇荐。

var obj = {
  a: undefined,
  b: function () {}
};

JSON.stringify(obj) // "{}"

上面代碼中洞就,對象obja屬性是undefined,而b屬性是一個函數(shù)掀淘,結果都被JSON.stringify過濾旬蟋。

如果數(shù)組的成員是undefined、函數(shù)或 XML 對象革娄,則這些值被轉成null咖为。

var arr = [undefined, function () {}];
JSON.stringify(arr) // "[null,null]"

上面代碼中秕狰,數(shù)組arr的成員是undefined和函數(shù),它們都被轉成了null躁染。

正則對象會被轉成空對象鸣哀。

JSON.stringify(/foo/) // "{}"

JSON.stringify方法會忽略對象的不可遍歷屬性。

var obj = {};
Object.defineProperties(obj, {
  'foo': {
    value: 1,
    enumerable: true
  },
  'bar': {
    value: 2,
    enumerable: false
  }
});

JSON.stringify(obj); // "{"foo":1}"

上面代碼中吞彤,barobj對象的不可遍歷屬性我衬,JSON.stringify方法會忽略這個屬性。

第二個參數(shù)

JSON.stringify方法還可以接受一個數(shù)組饰恕,作為第二個參數(shù)挠羔,指定需要轉成字符串的屬性。

var obj = {
  'prop1': 'value1',
  'prop2': 'value2',
  'prop3': 'value3'
};

var selectedProperties = ['prop1', 'prop2'];

JSON.stringify(obj, selectedProperties)
// "{"prop1":"value1","prop2":"value2"}"

上面代碼中埋嵌,JSON.stringify方法的第二個參數(shù)指定破加,只轉prop1prop2兩個屬性。

這個類似“白名單”的數(shù)組雹嗦,只對對象的屬性有效范舀,對數(shù)組無效。

JSON.stringify(['a', 'b'], ['0'])
// "["a","b"]"

JSON.stringify({0: 'a', 1: 'b'}, ['0'])
// "{"0":"a"}"

上面代碼中了罪,第二個參數(shù)指定JSON格式只轉0號屬性锭环,實際上對數(shù)組是無效的,只對對象有效泊藕。

第二個參數(shù)還可以是一個函數(shù)辅辩,用來更改JSON.stringify的默認行為。

function f(key, value) {
  if (typeof value === "number") {
    value = 2 * value;
  }
  return value;
}

JSON.stringify({ a: 1, b: 2 }, f)
// '{"a": 2,"b": 4}'

上面代碼中的f函數(shù)娃圆,接受兩個參數(shù)玫锋,分別是被轉換的對象的鍵名和鍵值。如果鍵值是數(shù)值讼呢,就將它乘以2撩鹿,否則就原樣返回。

注意吝岭,這個處理函數(shù)是遞歸處理所有的鍵三痰。

var o = {a: {b: 1}};

function f(key, value) {
  console.log("["+ key +"]:" + value);
  return value;
}

JSON.stringify(o, f)
// []:[object Object]
// [a]:[object Object]
// [b]:1
// '{"a":{"b":1}}'

上面代碼中吧寺,對象o一共會被f函數(shù)處理三次窜管。第一次鍵名為空喧枷,鍵值是整個對象o界斜;第二次鍵名為a,鍵值是{b: 1}虑粥;第三次鍵名為b赖条,鍵值為1失乾。

遞歸處理中常熙,每一次處理的對象,都是前一次返回的值碱茁。

var o = {a: 1};

function f(key, value) {
  if (typeof value === 'object') {
    return {b: 2};
  }
  return value * 2;
}

JSON.stringify(o,f)
// "{"b": 4}"

上面代碼中裸卫,f函數(shù)修改了對象o,接著JSON.stringify方法就遞歸處理修改后的對象o纽竣。

如果處理函數(shù)返回undefined或沒有返回值墓贿,則該屬性會被忽略。

function f(key, value) {
  if (typeof(value) === "string") {
    return undefined;
  }
  return value;
}

JSON.stringify({ a: "abc", b: 123 }, f)
// '{"b": 123}'

上面代碼中蜓氨,a屬性經(jīng)過處理后聋袋,返回undefined,于是該屬性被忽略了穴吹。

第三個參數(shù)

JSON.stringify還可以接受第三個參數(shù)幽勒,用于增加返回的JSON字符串的可讀性。如果是數(shù)字港令,表示每個屬性前面添加的空格(最多不超過10個)啥容;如果是字符串(不超過10個字符),則該字符串會添加在每行前面缠借。

JSON.stringify({ p1: 1, p2: 2 }, null, 2);
/*
"{
  "p1": 1,
  "p2": 2
}"
*/

JSON.stringify({ p1:1, p2:2 }, null, '|-');
/*
"{
|-"p1": 1,
|-"p2": 2
}"
*/

toJSON 方法

如果對象有自定義的toJSON方法干毅,那么JSON.stringify會使用這個方法的返回值作為參數(shù),而忽略原對象的其他屬性泼返。

下面是一個普通的對象硝逢。

var user = {
  firstName: '三',
  lastName: '張',

  get fullName(){
    return this.lastName + this.firstName;
  }
};

JSON.stringify(user)
// "{"firstName":"三","lastName":"張","fullName":"張三"}"

現(xiàn)在,為這個對象加上toJSON方法绅喉。

var user = {
  firstName: '三',
  lastName: '張',

  get fullName(){
    return this.lastName + this.firstName;
  },

  toJSON: function () {
    var data = {
      firstName: this.firstName,
      lastName: this.lastName
    };
    return data;
  }
};

JSON.stringify(user)
// "{"firstName":"三","lastName":"張"}"

上面代碼中渠鸽,JSON.stringify發(fā)現(xiàn)參數(shù)對象有toJSON方法,就直接使用這個方法的返回值作為參數(shù)柴罐,而忽略原對象的其他參數(shù)徽缚。

Date對象就有一個自己的toJSON方法。

var date = new Date('2015-01-01');
date.toJSON() // "2015-01-01T00:00:00.000Z"
JSON.stringify(date) // ""2015-01-01T00:00:00.000Z""

上面代碼中革屠,JSON.stringify發(fā)現(xiàn)處理的是Date對象實例凿试,就會調(diào)用這個實例對象的toJSON方法,將該方法的返回值作為參數(shù)似芝。

toJSON方法的一個應用是那婉,將正則對象自動轉為字符串。因為JSON.stringify默認不能轉換正則對象党瓮,但是設置了toJSON方法以后详炬,就可以轉換正則對象了。

var obj = {
  reg: /foo/
};

// 不設置 toJSON 方法時
JSON.stringify(obj) // "{"reg":{}}"

// 設置 toJSON 方法時
RegExp.prototype.toJSON = RegExp.prototype.toString;
JSON.stringify(/foo/) // ""/foo/""

上面代碼在正則對象的原型上面部署了toJSON方法寞奸,將其指向toString方法呛谜,因此遇到轉換成JSON時在跳,正則對象就先調(diào)用toJSON方法轉為字符串,然后再被JSON.stingify方法處理隐岛。

JSON.parse()

JSON.parse方法用于將JSON字符串轉化成對象猫妙。

JSON.parse('{}') // {}
JSON.parse('true') // true
JSON.parse('"foo"') // "foo"
JSON.parse('[1, 5, "false"]') // [1, 5, "false"]
JSON.parse('null') // null

var o = JSON.parse('{"name": "張三"}');
o.name // 張三

如果傳入的字符串不是有效的JSON格式,JSON.parse方法將報錯聚凹。

JSON.parse("'String'") // illegal single quotes
// SyntaxError: Unexpected token ILLEGAL

上面代碼中吐咳,雙引號字符串中是一個單引號字符串,因為單引號字符串不符合JSON格式元践,所以報錯韭脊。

為了處理解析錯誤,可以將JSON.parse方法放在try...catch代碼塊中单旁。

JSON.parse方法可以接受一個處理函數(shù)沪羔,用法與JSON.stringify方法類似。

function f(key, value) {
  if (key === ''){
    return value;
  }
  if (key === 'a') {
    return value + 10;
  }
}

var o = JSON.parse('{"a":1,"b":2}', f);
o.a // 11
o.b // undefined

參考鏈接

?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末象浑,一起剝皮案震驚了整個濱河市蔫饰,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌愉豺,老刑警劉巖篓吁,帶你破解...
    沈念sama閱讀 212,454評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異蚪拦,居然都是意外死亡杖剪,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,553評論 3 385
  • 文/潘曉璐 我一進店門驰贷,熙熙樓的掌柜王于貴愁眉苦臉地迎上來盛嘿,“玉大人,你說我怎么就攤上這事括袒〈握祝” “怎么了?”我有些...
    開封第一講書人閱讀 157,921評論 0 348
  • 文/不壞的土叔 我叫張陵锹锰,是天一觀的道長芥炭。 經(jīng)常有香客問我,道長恃慧,這世上最難降的妖魔是什么园蝠? 我笑而不...
    開封第一講書人閱讀 56,648評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮糕伐,結果婚禮上砰琢,老公的妹妹穿的比我還像新娘蘸嘶。我一直安慰自己良瞧,他們只是感情好陪汽,可當我...
    茶點故事閱讀 65,770評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著褥蚯,像睡著了一般挚冤。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上赞庶,一...
    開封第一講書人閱讀 49,950評論 1 291
  • 那天训挡,我揣著相機與錄音,去河邊找鬼歧强。 笑死澜薄,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的摊册。 我是一名探鬼主播肤京,決...
    沈念sama閱讀 39,090評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼茅特!你這毒婦竟也來了忘分?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 37,817評論 0 268
  • 序言:老撾萬榮一對情侶失蹤白修,失蹤者是張志新(化名)和其女友劉穎妒峦,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體兵睛,經(jīng)...
    沈念sama閱讀 44,275評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡肯骇,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,592評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了祖很。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片累盗。...
    茶點故事閱讀 38,724評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖突琳,靈堂內(nèi)的尸體忽然破棺而出若债,到底是詐尸還是另有隱情,我是刑警寧澤拆融,帶...
    沈念sama閱讀 34,409評論 4 333
  • 正文 年R本政府宣布蠢琳,位于F島的核電站,受9級特大地震影響镜豹,放射性物質(zhì)發(fā)生泄漏傲须。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 40,052評論 3 316
  • 文/蒙蒙 一趟脂、第九天 我趴在偏房一處隱蔽的房頂上張望泰讽。 院中可真熱鬧,春花似錦、人聲如沸已卸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,815評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽累澡。三九已至梦抢,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間愧哟,已是汗流浹背奥吩。 一陣腳步聲響...
    開封第一講書人閱讀 32,043評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留蕊梧,地道東北人霞赫。 一個月前我還...
    沈念sama閱讀 46,503評論 2 361
  • 正文 我出身青樓,卻偏偏與公主長得像肥矢,于是被迫代替她去往敵國和親绩脆。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,627評論 2 350

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

  • 一橄抹、JSON格式 JSON格式(JavaScript Object Notation)是一種用于數(shù)據(jù)交換的文本格式...
    周花花啊閱讀 878評論 0 3
  • JSON 對值的類型和格式有嚴格的規(guī)定靴迫。 **復合類型的值只能是數(shù)組或?qū)ο螅荒苁呛瘮?shù)楼誓、正則表達式對象玉锌、日期對象。...
    zjh111閱讀 392評論 0 0
  • JSON格式(JavaScript Object Notation)是一種用于數(shù)據(jù)交換的文本格式json格式規(guī)定:...
    秋秋秋web閱讀 203評論 0 0
  • ** 本文章著作權歸沒夢想的咸魚丶所有参淫,轉載須說明來源** 1.首先明確JSON是什么? json是一種數(shù)據(jù)交換格...
    沒夢想的咸魚丶閱讀 2,522評論 0 16
  • 如今微商創(chuàng)業(yè)已經(jīng)蓬勃發(fā)展起來愧杯,每天有人退出微商涎才,也有人加入微商。 這就是堅持跟不堅持力九,努力與不努力的區(qū)別耍铜。 做好微...
    書海無涯苦閱讀 1,474評論 1 2