Redis Lua Differetiating empty array and object

末鹿安然 提交于 2020-07-19 02:51:07

问题


I encountered this bug in cjson lua when I was using a script in redis 3.2 to set a particular value in a json object.

Currently, the lua in redis does not differentiate between an empty json array or an empty json object. Which causes serious problems when serialising json objects that have arrays within them.

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

Result:

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

I found this solution https://github.com/mpx/lua-cjson/issues/11 but I wasn't able to implement in a redis script.

This is an unsuccessful attempt :

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

Any help or pointer appreciated.


回答1:


There are two plans.

  1. Modify the lua-cjson source code and compile redis, click here for details.

  2. Fix by code:

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


来源:https://stackoverflow.com/questions/43272872/redis-lua-differetiating-empty-array-and-object

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!