JSON
JSON(JavaScript Object Notation)
是一種輕量級的數據交換格式。易於人閱讀和編寫。同時也易於機器解析和生成。它基於JavaScript Programming Language, Standard ECMA-262 3rd Edition - December 1999
的一個子集。
-
JSON
指的是 JavaScript 對象表示法(JavaScript Object Notation
) -
JSON
是輕量級的文本數據交換格式 -
JSON
獨立於語言:JSON 使用Javascript
語法來描述數據對象,但是 JSON 仍然獨立於語言和平臺。JSON 解析器和 JSON 庫支持許多不同的編程語言。 目前非常多的動態(PHP,JSP,.NET
)編程語言都支持JSON。 -
JSON
具有自我描述性,更易理解
JSON數據格式
JSON
大致3種結構,JSON
對象、JSON
數組和JSON
對象和數組嵌套。
Object對象
Object
是一個無序‘名稱/值’對
集合,一個對象以{
(左括號)開始,}
(右括號)結束。每個名稱
後跟一個:
(冒號);‘名稱/值’ 對
之間使用,
(逗號)分隔。
其中鍵值對中的鍵必須是string
類型,值可以是json三種Object|Array|value
類型中的一種,string
屬於一種value
,value
包含string、null、number
等,後面第三種會講
實例:
{}
{"aa": true}
{"bb": "3333"}
{"cc": null}
{"dd": {"ee": ["ff","gg"]}}
Array數組
數組是值(value)的有序集合。一個數組以[
(左中括號)開始,]
(右中括號)結束。值之間使用,
(逗號)分隔。
示例:
[]
["aa","bb"]
[[1,2],[3,4]]
[{"aa": []},{bb: []}]
值Value
值(value)
可以是雙引號括起來的字符串(string)、數值(number)、true、false、 null、對象(object)或者數組(array)
。這些結構可以嵌套。
string
string
是value
中比較特殊的需要注意的一種;字符串(string)是由雙引號包圍的任意數量Unicode字符的集合,使用反斜線轉義。一個字符(character)即一個單獨的字符串(character string)。
示例:
"aaa"
"\ttab"
"\nnew line"
看起來很簡單啊;結果我們去V8環境中運行了一下,
JSON.parse("\nnewline");
VM5802:2 Uncaught SyntaxError: Unexpected token e in JSON at position 2
at JSON.parse (<anonymous>)
at <anonymous>:1:6
(anonymous) @ VM5801:1
JSON.parse("\ttab");
VM5836:1 Uncaught SyntaxError: Unexpected token a in JSON at position 2
at JSON.parse (<anonymous>)
at <anonymous>:1:6
藍瘦了,不是說好的格式嗎?反向測試:
JSON.stringify('2 2')
""2\t2""
JSON.parse(JSON.stringify('2 2'))
"2 2"
JSON.stringify('2 2')
""2\t2""
JSON.parse('"2\t2"')
VM330:1 Uncaught SyntaxError: Unexpected number in JSON at position 2
at JSON.parse (<anonymous>)
at <anonymous>:1:6
問題好像有點眉頭了,爲什麼直接使用字符串的時候會有問題呢?是不是js的字符串定義和解析的鍋?MDN上的js的string
轉義字符節
除了普通的可打印字符以外,一些特殊有特殊功能的字符可以通過轉義字符的形式放入字符串中:
Code Output
\0 空字符
\' 單引號
\" 雙引號
\\ 反斜槓
\n 換行
\r 回車
\v 垂直製表符
\t 水平製表符
\b 退格
\f 換頁
\uXXXX unicode 碼
\u{X} ... \u{XXXXXX} unicode codepoint
\xXX Latin-1 字符(x小寫)
問題的根本原因在於使用V8的JSON.parse
的時候,參數會被V8先解析爲字符串;
'"\ttab"' =>
"" tab""
'"\nnewline"' =>
""
newline""
'"2\t2"' =>
""2 2""
被解析後的字符串變了樣子,這些解析後的字符串不再符合JSON的格式,所以解析就會報錯了。詳情參考:從一個 JSON.parse 錯誤深入研究 JavaScript 的轉義字符
number
數值(number)也與C或者Java的數值非常相似。除去未曾使用的八進制與十六進制格式。除去一些編碼細節。
javascript的JSON對象
JSON對象包含兩個方法: 用於解析 JavaScript Object Notation (JSON) 的 parse() 方法,以及將對象/值轉換爲 JSON字符串的 stringify() 方法。除了這兩個方法, JSON這個對象本身並沒有其他作用,也不能被調用或者作爲構造函數調用。
parse
JSON.parse()
方法用來解析JSON字符串,構造由字符串描述的JavaScript值或對象。提供可選的reviver函數用以在返回之前對所得到的對象執行變換(操作)。parse語法介紹和使用mdn
JSON.parse(text[, reviver])
>如果指定了 reviver 函數,則解析出的 JavaScript 值(解析值)會經過一次轉換後纔將被最終返回(返回值)。更具體點講就是:解析值本身以及它所包含的所有屬性,會按照一定的順序(從最最裏層的屬性開始,一級級往外,最終到達頂層,也就是解析值本身)分別的去調用 reviver 函數,在調用過程中,當前屬性所屬的對象會作爲 this 值,當前屬性名和屬性值會分別作爲第一個和第二個參數傳入 reviver 中。如果 reviver 返回 undefined,則當前屬性會從所屬對象中刪除,如果返回了其他值,則返回的值會成爲當前屬性新的屬性值。
>當遍歷到最頂層的值(解析值)時,傳入 reviver 函數的參數會是空字符串 ""(因爲此時已經沒有真正的屬性)和當前的解析值(有可能已經被修改過了),當前的 this 值會是 {"": 修改過的解析值},在編寫 reviver 函數時,要注意到這個特例。(這個函數的遍歷順序依照:從最內層開始,按照層級順序,依次向外遍歷)
stringify
JSON.stringify()
方法是將一個JavaScript值(對象或者數組)轉換爲一個 JSON字符串,如果指定了replacer是一個函數,則可以替換值,或者如果指定了replacer是一個數組,可選的僅包括指定的屬性。mdn文檔
JSON.stringify(value[, replacer [, space]])
需要注意後面連個參數,replacer
可以是函數或者數組;
- 數組的值代表將被序列化成JSON字符串的屬性名。
-
作爲函數,它有兩個參數,鍵(key)值(value)都會被序列化。
如果返回一個 Number, 轉換成相應的字符串被添加入JSON字符串。
如果返回一個 String, 該字符串作爲屬性值被添加入JSON。
如果返回一個 Boolean, "true" 或者 "false"被作爲屬性值被添加入JSON字符串。
如果返回任何其他對象,該對象遞歸地序列化成JSON字符串,對每個屬性調用replacer方法。除非該對象是一個函數,這種情況將不會被序列化成JSON字符串。
如果返回undefined,該屬性值不會在JSON字符串中輸出。
注意: 不能用replacer方法,從數組中移除值(values),如若返回undefined或者一個函數,將會被null取代。
space
參數用來控制結果字符串裏面的間距。如果是一個數字, 則在字符串化時每一級別會比上一級別縮進多這個數字值的空格(最多10個空格);如果是一個字符串,則每一級別會比上一級別多縮進用該字符串(或該字符串的前十個字符)。
fast-json-stringify
最近發現一個庫fast-json-stringify,因爲他的介紹很簡潔:2x faster than JSON.stringify()
;需要一探究竟。