JSON(JavaScript? 物件表示法)是基於 JavaScript? 資料結構格式的一種序列化資料格式。有關 JSON 的更多資訊,請參閱 http://www.json.org/ 和 [JSON 的維基百科文章]。
JSON 模組比較
由於有些模組僅稱為「json」,故新增開頭字母以建立唯一名稱
- cmj-JSON4Lua(版本 0.9.5)
- dkjson(版本 2.1)
- Fleece(版本 0.3.1)
- jf-JSON(版本 20160526.15)
- Lua-Yajl(版本 2.0)
- mp-CJSON / Lua CJSON(版本 1.0.2)
- sb-Json(2007 版本)
- th-LuaJSON(版本 1.2.1)
- luci.json(版本 0.11+)
- lunajson(版本 1.1)(由作者個別測試)
此比較一開始由 dkjson 作者 DavidKolf 開始,因此可能有所偏頗。
比較時使用預設選項。我(DavidKolf)預期模組會使用預設設定與 JSON 相容。針對 Fleece 開了個例外,此比較中大多數內容對選項「E4」以外的選項來說並不適用。
可以在 dkjson 儲存庫中找到 [功能/相容性測試] 和 [速度測試]。
其他 JSON 實作
未包含在此比較(尚未)的 JSON 實作
主要錯誤
- Fleece:
- 將 +/-math.huge(無限大)編碼會使程式凍結(無限迴圈)。
- 將區位碼>= 128 的 UTF-8 編碼會取消後續輸出。
- 參考循環會導致分段錯誤。
編碼時的轉義字元
根據 [RFC 4627],0 到 31 範圍內的所有字元加上 \\ 和 \" 都必須轉義。不過也建議轉義 U+2028 和 U+2029 Unicode 字元,以便 [產生有效的 JavaScript]。[原始 JSON 實作] 更進一步,並轉義大多數的控制字元和 BMP 中未定義的區位碼。
- cmj-JSON4Lua:\\、\"、\n、\t 和 \',其中 \' 不是有效的 JSON 轉義碼。包含此字元的 JSON 檔案無法在原始實作載入。
- dkjson:0 到 31 範圍內的所有字元、\\、\"、127 和其他在原始實作中由原始實作轉義的 Unicode 控制字元。
- Fleece(具有 E4 選項):0 到 31 範圍內的所有字元、\\、\"、\/、127。所有大於 127 的字元都將取消後續輸出。
- jf-JSON:0 到 31 範圍內的所有字元、\\、\"。可選擇性地轉義 U+2028 和 U+2029。
- Lua-Yajl:0 到 31 範圍內的所有字元、\\、\"。
- mp-CJSON:0 到 31 範圍內的所有字元、\\、\"、\/、127。
- sb-Json:0 到 31 範圍內的所有字元、\\、\"、\/、127。
- th-LuaJSON:0 到 31 範圍內的所有字元、\\、\"、\/、\u000b(11)轉義為 \v,這是無效的 JSON 碼,且無法在原始實作載入。
- lunajson:0 到 31 範圍內的所有字元、\\、\"。
解碼時支援 Unicode 轉義序列 \uXXXX
- cmj-JSON4Lua:不支援
- dkjson:完整支援 0 到 0x10ffff,正確轉換 [UTF-16] 代理對到 [UTF-8]。
- jf-JSON:完整支援 0 到 0x10ffff,正確轉換 UTF-16 代理對到 UTF-8。
- Lua-Yajl:完整支援 0 到 0x10ffff,正確轉換 UTF-16 代理對到 UTF-8。
- mp-CJSON:完整支援 0 到 0x10ffff,正確轉換 UTF-16 代理對到 UTF-8。
- sb-Json:支援 0 到 0xff 的範圍,建立 8 位元編碼(latin1 或類似編碼)。
- th-LuaJSON:支援範圍為 0 到 0xffff,但不會轉換 UTF-16 代理配對,因此 0x10000 到 0x10ffff 會編碼成 [CESU-8],而不是 UTF-8。
- lunajson:完整支援 0 到 0x10ffff,正確將 UTF-16 代理配對轉換成 UTF-8。
其他錯誤
- cmj-JSON4Lua:
- 解碼空陣列會引發錯誤。
- 解碼指數部分帶正號的數字會引發錯誤(「1e+2」)。
編碼的邊際範例
JSON 無法表示所有 Lua 結構。此部分列出一些情況下的行為。不應傳送任何這類資料給任何 JSON 模組,但模組如何處理這類資料仍令人感興趣。模組不得掛起或崩潰,並且不應產生無效的 JSON 輸出。(引發 Lua 錯誤是處理這種資料的有效方式)。
混合列表
{[1] = 1, a = 2}
稀疏陣列
{[1000] = "test"}
- cmj-JSON4Lua:編碼為大陣列。
- dkjson:編碼為具有字串鍵的物件。
- Fleece:編碼為具有整數鍵的物件(無效的 JSON)。
- jf-JSON:編碼為大陣列。
- Lua-Yajl:編碼為大陣列。
- mp-CJSON:對過度稀疏的陣列引發錯誤,並將其他稀疏陣列轉換成具有字串鍵的物件。行為可在執行階段組態。
- sb-Json:編碼為大陣列。
- th-LuaJSON:編碼為具有字串鍵的物件。
- luci.json:編碼為具有字串鍵的物件。
- lunajson:引發錯誤,除非明確指定陣列長度(陣列長度由索引 0 指定,例如 {[0] = 1000, [1000] = "test"})。
處理 NaN 和 Inf
nan = math.huge * 0
inf = math.huge
- cmj-JSON4Lua:原始 tostring() 輸出(無效的 JSON)。
- dkjson:'null'(如同原始的 JSON 實作)。
- Fleece:NaN 為 0.0000,在 +/-Inf 時凍結。
- jf-JSON:NaN 為 'null',Inf 為 1e+9999。
- Lua-Yajl:NaN 為 -0,Inf 為 1e+666。
- mp-CJSON:預設會引發無效的 JSON 錯誤,但可在執行階段組態('null' 或 Nan/Inf)。
- sb-Json:原始 tostring() 輸出(無效的 JSON)。
- th-LuaJSON:JavaScript? 常數:NaN 為 'NaN',Inf 為 'Infinity'(這是有效的 JavaScript?,但無效的 JSON)。
- luci.json:NaN 為 nan,inf 為 inf。
- lunajson:拋出錯誤(無效號碼)。
編碼時防止出現參考迴圈
a = {}
a.a = a
- cmj-JSON4Lua:不行,進入無限迴圈。
- dkjson:可以,拋出錯誤。
- Fleece:不行,造成分段錯誤。
- jf-JSON:可以,拋出錯誤。
- Lua-Yajl:可以,拋出錯誤。
- mp-CJSON:可以,拋出錯誤,可於執行階段設定限制。
- sb-Json:不行,進入無限迴圈。
- th-LuaJSON:可以,拋出錯誤。
- luci.json:可以,傳回 nil,但耗費「一些時間」執行此操作(消耗 CPU)。
- lunajson:可以,拋出錯誤。
處理空陣列
local json_str = '{"items":[],"properties":{}}'
assert(json_str == json.encode(json.decode(json_str)))
- cmj-JSON4Lua:無法正確運作(空陣列編碼為單純的空表格)。
- dkjson:可以正確運作(在 metatable 上使用「類型欄位」)。
- Fleece:未測試。
- jf-JSON:可以選擇正確運作;預設為空表格總是編碼為空物件。
- Lua-Yajl:無法正確運作(空表格總是編碼為空陣列)。
- mp-CJSON:無法正確運作(空表格總是編碼為空物件)。
- sb-Json:未測試。
- th-LuaJSON:可以運作(為陣列分配特別的 metatable)(v1.3)。
- luci.json:解碼為 nil,空表格總是編碼為空陣列。
- lunajson:如果將編碼陣列長度的選項傳遞給解碼器,可以正確運作。
編碼速度
- cmj-JSON4Lua:12 秒
- dkjson:16 秒
- Fleece:0.5 秒
- jf-JSON:20 秒
- Lua-Yajl:5.9 秒
- mp-CJSON:1 秒
- sb-Json:22 秒
- th-LuaJSON:30 秒
解碼速度
- cmj-JSON4Lua:47 秒
- dkjson:無 LPeg 為 28 秒,有 LPeg 為 8 秒
- jf-JSON:30 秒
- Lua-Yajl:4 秒
- mp-CJSON:2 秒
- sb-Json:122 秒
- th-LuaJSON:9 秒(版本 1.2.2 花費 347 秒)
速度測試編碼或解碼一個表格 100000 次。數值不夠精確,使用其他資料時可能會有差異,但應該可以提供一般資訊。FIXME - 不知道表格是什麼,很難在此執行新的測試?
另見
- [JSONRPC4Lua] (5.0/5.1) - Lua 透過 http 的 JSON-RPC 執行個體(或在 CGILua 環境中的伺服器)。
近期異動 · 喜好設定
編輯 · 歷程記錄
最後編輯 2018 年 8 月 5 日 (星期日) 上午 6:27 GMT (差異)