Redis Lua:区分空数组和对象

6

当我在redis 3.2中使用脚本设置JSON对象中的特定值时,遇到了cjson lua中的一个bug。

目前,redis中的lua无法区分空的JSON数组和空的JSON对象。这会在序列化具有数组的JSON对象时导致严重问题。

eval "local json_str = '{\"items\":[],\"properties\":{}}' return cjson.encode(cjson.decode(json_str))" 0

结果:

"{\"items\":{},\"properties\":{}}"

我找到了这个解决方案https://github.com/mpx/lua-cjson/issues/11,但我无法在redis脚本中实现它。
这是一个失败的尝试:
eval 

"function cjson.mark_as_array(t) 
local mt = getmetatable(t) or {} 
mt.__is_cjson_array = true 
return setmetatable(t, mt) 
end 
function cjson.is_marked_as_array(t) 
local mt = getmetatable(t) 
return mt and mt.__is_cjson_array end 
local json_str = '{\"items\":[],\"properties\":{}}' 
return cjson.encode(cjson.decode(json_str))" 

0

任何帮助或指针都将不胜感激。
1个回答

1

有两个方案。

  1. 修改lua-cjson源代码并编译redis,点击这里了解详情。

  2. 通过代码修复问题:

local now = redis.call("time")
-- local timestamp = tonumber(now[1]) * 1000 + math.floor(now[2]/1000)
math.randomseed(now[2])
local emptyFlag = "empty_" .. now[1] .. "_" .. now[2] .. "_" .. math.random(10000)
local emptyArrays = {}
local function emptyArray()
    if cjson.as_array then
        -- cjson fixed:  https://github.com/xiyuan-fengyu/redis-lua-cjson-empty-table-fix
        local arr = {}
        setmetatable(arr, cjson.as_array)
        return arr
    else
        -- plan 2
        local arr = {}
        table.insert(emptyArrays, arr)
        return arr
    end
end

local function toJsonStr(obj)
    if #emptyArrays > 0 then
        -- plan 2
        for i, item in ipairs(emptyArrays) do
            if #item == 0 then
                -- empty array, insert a special mark
                table.insert(item, 1, emptyFlag)
            end
        end

        local jsonStr = cjson.encode(obj)
        -- replace empty array
        jsonStr = (string.gsub(jsonStr, '%["' .. emptyFlag ..  '"]', "[]"))

        for i, item in ipairs(emptyArrays) do
            if item[1] == emptyFlag then
                table.remove(item, 1)
            end
        end
        return jsonStr
    else
        return cjson.encode(obj)
    end
end


-- example
local arr = emptyArray()
local str = toJsonStr(arr)
print(str) -- "[]"

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接