JSON 是一種用於數據交換的文本格式,誕生於 2001 年由Douglas Crockford提出,目的是取代繁瑣笨重的XML格式。這種格式不僅人很容易進行閱讀和編寫,同時機器也很容易解析和生成,是當前十分流行的數據格式,尤其是在前端領域。
JSON是什么
JSON,全稱是 JavaScript Object Notation,即 JavaScript 對象標記法。這是一種 輕量級 (Light-Weight)、 基於文本的 (Text-Based)、 可讀的 (Human-Readable)格式。
JSON 無論對於人,還是對於機器來說,都是十分便於閱讀和書寫的,而且相比 XML 文件更小;
JSON 格式的創始人聲稱此格式永遠不升級,這就表示這種格式具有長時間的穩定性;
JSON格式有兩個顯著的優點:書寫簡單,一目了然;符合JavaScript原生語法,可以由解釋引擎直接處理,不用另外添加解析代碼。
JSON已經成為各大網站交換數據的標准格式,並被寫入ECMAScript 5,成為標准的一部分。
簡單說,每個JSON對象,就是一個值。要么是簡單類型的值,要么是復合類型的值,但是只能是一個值,不能是兩個或更多的值。這就是說,每個JSON文檔只能包含一個值。
JSON對值的類型和格式有嚴格的規定
- 復合類型的值只能是數組或對象,不能是函數、正則表達式對象、日期對象。
- 簡單類型的值只有四種:字符串、數值(必須以十進制表示)、布爾值和null(不能使用NaN, Infinity, -Infinity和undefined)。
- 字符串必須使用雙引號表示,不能使用單引號。
- 對象的鍵名必須放在雙引號里面。
- 數組或對象最后一個成員的后面,不能加逗號。
PS: 需要注意的是,空數組和空對象都是合格的JSON值,null本身也是一個合格的JSON值。
JSON 的語法規則
JSON 的語法規則十分簡單,可稱得上“優雅完美”,總結起來有:
- 數組(Array)用方括號(“[]”)表示。
- 對象(Object)用大括號(”{}”)表示。
- 名稱/值對(name/value)組合成數組和對象。
- 名稱(name)置於雙引號中,值(value)有字符串、數值、布爾值、null、對象和數組。
- 並列的數據之間用逗號(“,”)分隔
//json對象 { "name": "Geoff Lui", "age": 26, "isChinese": true } //“名稱/值對”里,值可以是數組和對象,例如: { "name": "Geoff Lui", "age": 26, "isChinese": true, "friends":["Lucy", "Lily", "Gwen"], "Mother": { "name": "Mary Lui", "age": 54 } }
ES5新增了JSON對象,用來處理JSON格式數據。它有兩個方法: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、函數或 XML 對象,這個成員會被過濾掉。
var obj = { a: undefined, b: function () {} }; JSON.stringify(obj) // "{}"
上面代碼中,對象obj的a屬性是undefined,而b屬性是一個函數,結果都被JSON.stringify過濾。
如果數組的成員是undefined、函數或 XML 對象,則這些值被轉成null。
var arr = [undefined, function () {}]; JSON.stringify(arr) // "[null,null]"
上面代碼中,數組arr的成員是undefined和函數,它們都被轉成了null。
正則對象會被轉成空對象。
JSON.stringify(/foo/) // "{}"
JSON.stringify方法還可以接受一個數組,作為第二個參數,指定需要轉成字符串的屬性。
1 var obj = { 2 'prop1': 'value1', 3 'prop2': 'value2', 4 'prop3': 'value3' 5 }; 6 7 var selectedProperties = ['prop1', 'prop2']; 8 9 JSON.stringify(obj, selectedProperties) 10 // "{"prop1":"value1","prop2":"value2"}"
上面代碼中,JSON.stringify方法的第二個參數指定,只轉prop1和prop2兩個屬性。
這個類似“白名單”的數組,只對對象的屬性有效,對數組無效。
第二個參數還可以是一個函數,用來更改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函數,接受兩個參數,分別是被轉換的對象的鍵名和鍵值。如果鍵值是數值,就將它乘以2,否則就原樣返回。
注意,這個處理函數是遞歸處理所有的鍵。
JSON.stringify還可以接受第三個參數,用於增加返回的JSON字符串的可讀性。如果是數字,表示每個屬性前面添加的空格(最多不超過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
}"
*/
如果JSON.stringify的參數對象有自定義的toJSON方法,那么JSON.stringify會使用這個方法的返回值作為參數,而忽略原對象的其他屬性。(略)
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方法可以接受一個處理函數,用法與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
參考
[1] 阮一峰,JSON對象
