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)(由作者单独测试)
此比较最初由 DavidKolf(dkjson 的作者)发起,因此可能存在偏差。
为了比较,使用了默认选项。我(DavidKolf)期望模块在默认设置下与 JSON 兼容。Fleece 进行了例外处理,大多数比较对于除“E4”选项之外的任何其他选项都没有意义。
dkjson 的存储库中可以找到 [功能/合规性测试] 和 [速度测试]。
其他 JSON 实现
尚未包含在此比较中的 JSON 实现
主要错误
- Fleece:
- 编码 +/-math.huge(无穷大)会冻结程序(无限循环)。
- 编码大于等于 128 的代码点的 UTF-8 代码会取消进一步输出。
- 引用循环会导致段错误。
编码时的转义字符
根据 [RFC 4627],范围为 0 到 31 的所有字符以及 \\ 和 \" 都必须转义。但是,建议还转义 Unicode 字符 U+2028 和 U+2029 以 [生成有效的 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: 工作正常(在元表上使用“类型字段”)
- Fleece: 未测试
- jf-JSON: 可选地工作正常;默认情况下,空表始终被编码为空对象
- Lua-Yajl: 工作不正常(空表始终被编码为空数组)
- mp-CJSON: 工作不正常(空表始终被编码为空对象)
- sb-Json: 未测试
- th-LuaJSON: (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 的 JSON-RPC-over-http 客户端(或在 CGILua 环境中的服务器)。
最近更改 · 偏好设置
编辑 · 历史记录
最后编辑于 2018 年 8 月 5 日上午 6:27 GMT (差异)