From ab4ca779a00d3114f12e6fbd07e7ef19419c692f Mon Sep 17 00:00:00 2001 From: Carlos Scheidegger <285675+cscheid@users.noreply.github.com> Date: Mon, 21 Oct 2024 21:08:18 +0200 Subject: [PATCH 1/3] Support nil in table / null in array --- json.lua | 53 +++++++++++++++++++++++++++------------------------ test/test.lua | 16 +++++++++++++--- 2 files changed, 41 insertions(+), 28 deletions(-) diff --git a/json.lua b/json.lua index 711ef78..39c0de4 100644 --- a/json.lua +++ b/json.lua @@ -55,6 +55,9 @@ local function encode_nil(val) return "null" end +local function encode_string(val) + return '"' .. val:gsub('[%z\1-\31\\"]', escape_char) .. '"' +end local function encode_table(val, stack) local res = {} @@ -65,44 +68,44 @@ local function encode_table(val, stack) 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 + local types = {} + + for k in pairs(val) do + types[type(k)] = true + end + + if #types > 1 then + error("invalid table: mixed or invalid key types") + elseif types["number"] then + -- Treat as array + local max_key = 0 for k in pairs(val) do - if type(k) ~= "number" then - error("invalid table: mixed or invalid key types") + if k > max_key then + max_key = k end - n = n + 1 - end - if n ~= #val then - error("invalid table: sparse array") end - -- Encode - for i, v in ipairs(val) do - table.insert(res, encode(v, stack)) + for i = 1, max_key do + if val[i] == nil then + table.insert(res, "null") + else + local v = encode(val[i], stack) + table.insert(res, v) + end end stack[val] = nil return "[" .. table.concat(res, ",") .. "]" - - else - -- Treat as an object + elseif types["string"] then + -- Treat as object for k, v in pairs(val) do - if type(k) ~= "string" then - error("invalid table: mixed or invalid key types") - end - table.insert(res, encode(k, stack) .. ":" .. encode(v, stack)) + table.insert(res, encode_string(k) .. ":" .. encode(v, stack)) end stack[val] = nil return "{" .. table.concat(res, ",") .. "}" + else + error( string.format("invalid table: unsupported key type %s", types[1]) ) end end - -local function encode_string(val) - return '"' .. val:gsub('[%z\1-\31\\"]', escape_char) .. '"' -end - - local function encode_number(val) -- Check for NaN, -inf and inf if val ~= val or val <= -math.huge or val >= math.huge then diff --git a/test/test.lua b/test/test.lua index 74470b2..0ea790e 100644 --- a/test/test.lua +++ b/test/test.lua @@ -91,6 +91,19 @@ test("arrays", function() end) +test("arrays with nil / null", function() + local t = { + { [1000] = "b" }, + { nil, 2, 3, 4 }, + { nil, "test" }, + { [1] = "a", [3] = "b" }, + } + for i, v in ipairs(t) do + assert( equal( v, json.decode( json.encode(v) ) ) ) + end +end) + + test("objects", function() local t = { x = 10, y = 20, z = 30 } assert( equal( t, json.decode( json.encode(t) ) ) ) @@ -203,11 +216,8 @@ end) test("encode invalid", function() local t = { - { [1000] = "b" }, { [ function() end ] = 12 }, - { nil, 2, 3, 4 }, { x = 10, [1] = 2 }, - { [1] = "a", [3] = "b" }, { x = 10, [4] = 5 }, } for i, v in ipairs(t) do From 7d4abf179947cc12c63a88e1c802e5511bd0c0c7 Mon Sep 17 00:00:00 2001 From: winniehell Date: Mon, 21 Oct 2024 21:45:03 +0200 Subject: [PATCH 2/3] Add failing test for encoding empty table --- test/test.lua | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/test/test.lua b/test/test.lua index 0ea790e..d01edc3 100644 --- a/test/test.lua +++ b/test/test.lua @@ -110,6 +110,18 @@ test("objects", function() end) +test("encode empty", function() + local t = { + [ '[]' ] = {}, + [ '""' ] = "", + } + for k, v in pairs(t) do + local res = json.encode(v) + assert( equal(res, k), fmt("'%s' did not equal expected %s", res, k) ) + end +end) + + --test("strict decode", function() -- local t = { -- '{x : 1}', From 50996379712510733270784549313afbd19be619 Mon Sep 17 00:00:00 2001 From: winniehell Date: Mon, 21 Oct 2024 21:57:04 +0200 Subject: [PATCH 3/3] Fix encoding of empty table --- json.lua | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/json.lua b/json.lua index 39c0de4..aa55379 100644 --- a/json.lua +++ b/json.lua @@ -68,6 +68,10 @@ local function encode_table(val, stack) stack[val] = true + if next(val) == nil then + return '[]' + end + local types = {} for k in pairs(val) do