【问题标题】:Redis Lua Differetiating empty array and objectRedis Lua区分空数组和对象
【发布时间】:2017-09-02 12:40:55
【问题描述】:

当我在 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

任何帮助或指针表示赞赏。

【问题讨论】:

    标签: json lua redis cjson


    【解决方案1】:

    有两个计划。

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

    【讨论】:

      猜你喜欢
      • 2021-12-20
      • 2020-06-09
      • 1970-01-01
      • 2019-01-13
      • 1970-01-01
      • 2021-06-27
      • 2017-06-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多