local json = {} local escapes = { ['"'] = '\\"', ['\\'] = '\\\\', ['\b'] = '\\b', ['\f'] = '\\f', ['\n'] = '\\n', ['\r'] = '\\r', ['\t'] = '\\t', } local function is_array(t) local max = 0 local count = 0 for k, _ in pairs(t) do if type(k) ~= "number" or k < 1 or k % 1 ~= 0 then return false end if k > max then max = k end count = count + 1 end return max == count end local function encode_string(s) return '"' .. tostring(s):gsub('[%z\1-\31\\"]', function(c) return escapes[c] or string.format("\\u%04x", c:byte()) end) .. '"' end local function encode_value(v) local tv = type(v) if tv == "nil" then return "null" elseif tv == "boolean" then return v and "true" or "false" elseif tv == "number" then return tostring(v) elseif tv == "string" then return encode_string(v) elseif tv == "table" then local out = {} if is_array(v) then for i = 1, #v do out[#out + 1] = encode_value(v[i]) end return "[" .. table.concat(out, ",") .. "]" end local keys = {} for k, _ in pairs(v) do keys[#keys + 1] = k end table.sort(keys, function(a, b) return tostring(a) < tostring(b) end) for _, k in ipairs(keys) do out[#out + 1] = encode_string(k) .. ":" .. encode_value(v[k]) end return "{" .. table.concat(out, ",") .. "}" end error("cannot JSON encode " .. tv) end function json.encode(v) return encode_value(v) end return json