Redis Lua区分空数组和对象

时间:2017-04-07 08:04:51

标签: json lua redis cjson

当我在redis 3.2中使用脚本在json对象中设置特定值时,我在cjson lua中遇到了这个错误。

目前,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 个答案:

答案 0 :(得分:0)

有两个计划。

  1. 修改lua-cjson源代码并编译redis,单击here了解详细信息。

  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) -- "[]"