local skynet = require "skynet"
local cjson = require("cjson")

local pairs = pairs
local tostring = tostring
local type = type
local xpcall = xpcall
local string_format = string.format

-- 设置 处理稀疏数组
-- https://www.kyne.com.au/~mark/software/lua-cjson-manual.html#encode_sparse_array
cjson.encode_sparse_array(true, 1, 1)

-- https://github.com/cloudwu/lua-cjson/pull/8
cjson.encode_empty_table_as_array("on")

-- https://github.com/cloudwu/lua-cjson/pull/10
cjson.encode_number_precision(16)

local json = {}

function json.check(var, str)
    str = str or "root"
    for k, v in pairs(var or {}) do
        local tstr = string_format("%s[%s]", str, tostring(k))
        if type(k) == "number" and k > 1 and not var[k - 1] then
            skynet.error("json check", tstr, "is a unvalided number")
        end
        if type(v) == "table" then
            json.check(v, tstr)
        end
    end
end

function json.encode(var)
    local function _logExce(errLog)
        skynet.error(var, errLog)
        json.check(var)
    end

    local status, result = xpcall(cjson.encode, _logExce, var)
    if status then
        return result
    end
end

function json.decode(text)
    if not text then
        return
    end

    local function _logExce(errLog)
        skynet.error("json decode", text, errLog)
    end

    local status, result = xpcall(cjson.decode, _logExce, text)
    if status then
        return result
    end
end

function json.test()
    local var = {
        [1] = {"ssss"},
        [2] = 2 ^ 53,
        [1000] = {
            [50] = "test",
            [3000] = {"data"},
        },
    }

    local str = json.encode(var)
    skynet.error("json test 1:%s", str)

    var = {}
    str = json.encode(var)
    skynet.error("json test 2:%s xxx", str)
end

-- json.test()

return json
