首先大家請(qǐng)看這段源碼:
-- http://www.kyne.com.au/~mark/software/lua-cjson.php
-- version: 2.1 devel
local json = require("cjson")
ngx.say("value --> ", json.encode({dogs={}}))
輸出結(jié)果
value --> {"dogs":{}}
注意看下 encode 后 key 的值類型,"{}" 代表 key 的值是個(gè) object,"[]" 則代表 key 的值是個(gè)數(shù)組。對(duì)于強(qiáng)類型語(yǔ)言(C/C++, Java 等),這時(shí)候就有點(diǎn)不爽。因?yàn)轭愋筒皇撬谕囊鋈蒎e(cuò)。對(duì)于 Lua 本身,是把數(shù)組和字典融合到一起了,所以他是無(wú)法區(qū)分空數(shù)組和空字典的。
參考 openresty/lua-cjson 中額外貼出測(cè)試案例,我們就很容易找到思路了。
-- 內(nèi)容節(jié)選lua-cjson-2.1.0.2/tests/agentzh.t
=== TEST 1: empty tables as objects
--- lua
local cjson = require "cjson"
print(cjson.encode({}))
print(cjson.encode({dogs = {}}))
--- out
{}
{"dogs":{}}
=== TEST 2: empty tables as arrays
--- lua
local cjson = require "cjson"
cjson.encode_empty_table_as_object(false)
print(cjson.encode({}))
print(cjson.encode({dogs = {}}))
--- out
[]
{"dogs":[]}
綜合本章節(jié)提到的各種問(wèn)題,我們可以封裝一個(gè) json_encode
的示例函數(shù):
local json = require("cjson")
--稀疏數(shù)組會(huì)被處理成object
json.encode_sparse_array(true)
local function _json_encode(data)
return json.encode(data)
end
function json_encode( data, empty_table_as_object )
--Lua的數(shù)據(jù)類型里面,array和dict是同一個(gè)東西。對(duì)應(yīng)到j(luò)son encode的時(shí)候,就會(huì)有不同的判斷
--cjson對(duì)于空的table,就會(huì)被處理為object,也就是{}
--處理方法:對(duì)于cjson,使用encode_empty_table_as_object這個(gè)方法。
json.encode_empty_table_as_object(empty_table_as_object or false) -- 空的table默認(rèn)為array
local ok, json_value = pcall(_json_encode, data)
if not ok then
return nil
end
return json_value
end
另一種思路是,使用 setmetatable(data, json.empty_array_mt)
,來(lái)標(biāo)記特定的 table,讓 cjson 在編碼這個(gè)空 table 時(shí)把它處理成 array:
local data = {}
setmetatable(data, json.empty_array_mt)
ngx.say("empty array: ", json.encode(data)) -- empty array: []