JSON.stringify和fast-json-stringify的比較

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是一個無序‘名稱/值’對集合,一個對象以{(左括號)開始,}(右括號)結束。每個名稱後跟一個:(冒號);‘名稱/值’ 對之間使用,(逗號)分隔。

clipboard.png
其中鍵值對中的鍵必須是string類型,值可以是json三種Object|Array|value類型中的一種,string屬於一種valuevalue包含string、null、number等,後面第三種會講
實例:

{}
{"aa": true}
{"bb": "3333"}
{"cc": null}
{"dd": {"ee": ["ff","gg"]}}

Array數組

數組是值(value)的有序集合。一個數組以[(左中括號)開始,](右中括號)結束。值之間使用,(逗號)分隔。

clipboard.png

示例:

[]
["aa","bb"]
[[1,2],[3,4]]
[{"aa": []},{bb: []}]

值Value

(value)可以是雙引號括起來的字符串(string)、數值(number)、true、false、 null、對象(object)或者數組(array)。這些結構可以嵌套。

clipboard.png

string

stringvalue中比較特殊的需要注意的一種;字符串(string)是由雙引號包圍的任意數量Unicode字符的集合,使用反斜線轉義。一個字符(character)即一個單獨的字符串(character string)。

clipboard.png

示例:

"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的數值非常相似。除去未曾使用的八進制與十六進制格式。除去一些編碼細節。

clipboard.png

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();需要一探究竟。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章