diff --git a/README.md b/README.md index 96b9b66..e626e48 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ A lightweight JSON library for Lua ## Features -* Implemented in pure Lua: works with 5.1, 5.2, 5.3 and JIT +* Implemented in pure Lua: works with 5.1, 5.2, 5.3, 5.4 and JIT * Fast: generally outperforms other pure Lua JSON implementations ([benchmark scripts](bench/)) * Tiny: around 280sloc, 9kb diff --git a/json.lua b/json.lua index 711ef78..372e69e 100644 --- a/json.lua +++ b/json.lua @@ -2,6 +2,7 @@ -- json.lua -- -- Copyright (c) 2020 rxi +-- Copyright (c) 2020 alexandro-rezakhani -- -- Permission is hereby granted, free of charge, to any person obtaining a copy of -- this software and associated documentation files (the "Software"), to deal in @@ -22,7 +23,7 @@ -- SOFTWARE. -- -local json = { _version = "0.1.2" } +local json = { _version = "0.1.2fix" } ------------------------------------------------------------------------------- -- Encode @@ -64,22 +65,30 @@ local function encode_table(val, stack) if stack[val] then error("circular reference") end stack[val] = true - - if rawget(val, 1) ~= nil or next(val) == nil then - -- Treat as array -- check keys are valid and it is not sparse - local n = 0 - for k in pairs(val) do - if type(k) ~= "number" then - error("invalid table: mixed or invalid key types") - end - n = n + 1 - end - if n ~= #val then - error("invalid table: sparse array") - end + -- Check whether to treat as a array or object + local array = true + local length = 0 + local nLen = 0 + for k,v in pairs(val) do + if (type(k) ~= "number" or k<=0) and not (k == "n" and type(v) == "number") then + array = nil + break -- Treat as object + else + if k > length then + length = k + end + if k == "n" and type(v) == "number" then + nLen = v + end + end + end + if array then + if nLen > length then + length = nLen + end -- Encode - for i, v in ipairs(val) do - table.insert(res, encode(v, stack)) + for i=1,length do + table.insert(res, encode(val[i], stack)) end stack[val] = nil return "[" .. table.concat(res, ",") .. "]" @@ -87,10 +96,13 @@ local function encode_table(val, stack) else -- Treat as an object for k, v in pairs(val) do - if type(k) ~= "string" then - error("invalid table: mixed or invalid key types") + if type(k) == "string" then + res[#res + 1] = encode(k, stack) .. ":" .. encode(v, stack) + elseif type(k) == "number" then + res[#res + 1] = encode(string.format(k), stack) .. ":" .. encode(v, stack) + else + error("invalid table: mixed or invalid key types"); end - table.insert(res, encode(k, stack) .. ":" .. encode(v, stack)) end stack[val] = nil return "{" .. table.concat(res, ",") .. "}" @@ -108,7 +120,12 @@ local function encode_number(val) if val ~= val or val <= -math.huge or val >= math.huge then error("unexpected number value '" .. tostring(val) .. "'") end - return string.format("%.14g", val) + local intVal = math.tointeger(val) + if intVal == val then + return string.format("%d", intVal) + else + return string.format("%.14g", val) + end end