-- Data-only JSON encoder; no executable configuration. return function(value) local function quote(s) return '"'..s:gsub('[%z\1-\31\\"]',function(c) if c=='"'then return '\\"'elseif c=='\\'then return '\\\\'end return string.format('\\u%04x',c:byte()) end)..'"' end local seen={};local function enc(v,depth) assert(depth<16,'JSON depth bound');local kind=type(v) if kind=='string'then return quote(v) elseif kind=='number'then assert(v==v and v~=math.huge and v~=-math.huge,'nonfinite JSON');return string.format('%.17g',v) elseif kind=='boolean'then return v and 'true'or'false' elseif kind=='nil'then return 'null'end assert(kind=='table'and not seen[v],'invalid JSON value');seen[v]=true local n,arr=0,true;for k in pairs(v)do n=n+1;if type(k)~='number'or k<1 or k%1~=0 then arr=false end end if arr and n~=#v then arr=false end local parts={};local indent=string.rep(' ',depth+1) if arr then for i=1,n do parts[#parts+1]=indent..enc(v[i],depth+1)end else local keys={};for k in pairs(v)do assert(type(k)=='string');keys[#keys+1]=k end;table.sort(keys) for _,k in ipairs(keys)do parts[#parts+1]=indent..quote(k)..': '..enc(v[k],depth+1)end end seen[v]=nil return (arr and '['or'{')..'\n'..table.concat(parts,',\n')..'\n'..string.rep(' ',depth)..(arr and ']'or'}') end return enc(value,0) end