mirror of
https://github.com/SquidDev-CC/CC-Tweaked
synced 2025-09-08 13:25:58 +00:00
Serialise sparse arrays into JSON (#685)
This commit is contained in:
@@ -381,6 +381,7 @@ local function serializeJSONImpl(t, tTracking, bNBTStyle)
|
||||
local sArrayResult = "["
|
||||
local nObjectSize = 0
|
||||
local nArraySize = 0
|
||||
local largestArrayIndex = 0
|
||||
for k, v in pairs(t) do
|
||||
if type(k) == "string" then
|
||||
local sEntry
|
||||
@@ -395,10 +396,17 @@ local function serializeJSONImpl(t, tTracking, bNBTStyle)
|
||||
sObjectResult = sObjectResult .. "," .. sEntry
|
||||
end
|
||||
nObjectSize = nObjectSize + 1
|
||||
elseif type(k) == "number" and k > largestArrayIndex then --the largest index is kept to avoid losing half the array if there is any single nil in that array
|
||||
largestArrayIndex = k
|
||||
end
|
||||
end
|
||||
for _, v in ipairs(t) do
|
||||
local sEntry = serializeJSONImpl(v, tTracking, bNBTStyle)
|
||||
for k = 1, largestArrayIndex, 1 do --the array is read up to the very last valid array index, ipairs() would stop at the first nil value and we would lose any data after.
|
||||
local sEntry
|
||||
if t[k] == nil then --if the array is nil at index k the value is "null" as to keep the unused indexes in between used ones.
|
||||
sEntry = "null"
|
||||
else -- if the array index does not point to a nil we serialise it's content.
|
||||
sEntry = serializeJSONImpl(t[k], tTracking, bNBTStyle)
|
||||
end
|
||||
if nArraySize == 0 then
|
||||
sArrayResult = sArrayResult .. sEntry
|
||||
else
|
||||
|
@@ -70,6 +70,105 @@ describe("The textutils library", function()
|
||||
expect.error(textutils.serialiseJSON, nil):eq("bad argument #1 (expected table, string, number or boolean, got nil)")
|
||||
expect.error(textutils.serialiseJSON, "", 1):eq("bad argument #2 (expected boolean, got number)")
|
||||
end)
|
||||
|
||||
it("serializes empty arrays", function()
|
||||
expect(textutils.serializeJSON(textutils.empty_json_array)):eq("[]")
|
||||
end)
|
||||
|
||||
it("serializes null", function()
|
||||
expect(textutils.serializeJSON(textutils.json_null)):eq("null")
|
||||
end)
|
||||
|
||||
it("serializes strings", function()
|
||||
expect(textutils.serializeJSON('a')):eq('"a"')
|
||||
expect(textutils.serializeJSON('"')):eq('"\\""')
|
||||
expect(textutils.serializeJSON('\\')):eq('"\\\\"')
|
||||
expect(textutils.serializeJSON('/')):eq('"/"')
|
||||
expect(textutils.serializeJSON('\b')):eq('"\\b"')
|
||||
expect(textutils.serializeJSON('\n')):eq('"\\n"')
|
||||
expect(textutils.serializeJSON(string.char(0))):eq('"\\u0000"')
|
||||
expect(textutils.serializeJSON(string.char(0x0A))):eq('"\\n"')
|
||||
expect(textutils.serializeJSON(string.char(0x1D))):eq('"\\u001D"')
|
||||
expect(textutils.serializeJSON(string.char(0x81))):eq('"\\u0081"')
|
||||
expect(textutils.serializeJSON(string.char(0xFF))):eq('"\\u00FF"')
|
||||
end)
|
||||
|
||||
it("serializes arrays until the last index with content", function()
|
||||
expect(textutils.serializeJSON({ 5, "test", nil, nil, 7 })):eq('[5,"test",null,null,7]')
|
||||
expect(textutils.serializeJSON({ 5, "test", nil, nil, textutils.json_null })):eq('[5,"test",null,null,null]')
|
||||
expect(textutils.serializeJSON({ nil, nil, nil, nil, "text" })):eq('[null,null,null,null,"text"]')
|
||||
end)
|
||||
end)
|
||||
|
||||
describe("textutils.unserializeJSON", function()
|
||||
describe("parses", function()
|
||||
it("a list of primitives", function()
|
||||
expect(textutils.unserializeJSON('[1, true, false, "hello"]')):same { 1, true, false, "hello" }
|
||||
end)
|
||||
|
||||
it("null when parse_null is true", function()
|
||||
expect(textutils.unserializeJSON("null", { parse_null = true })):eq(textutils.json_null)
|
||||
end)
|
||||
|
||||
it("null when parse_null is false", function()
|
||||
expect(textutils.unserializeJSON("null", { parse_null = false })):eq(nil)
|
||||
end)
|
||||
|
||||
it("an empty array", function()
|
||||
expect(textutils.unserializeJSON("[]", { parse_null = false })):eq(textutils.empty_json_array)
|
||||
end)
|
||||
|
||||
it("basic objects", function()
|
||||
expect(textutils.unserializeJSON([[{ "a": 1, "b":2 }]])):same { a = 1, b = 2 }
|
||||
end)
|
||||
end)
|
||||
|
||||
describe("parses using NBT-style syntax", function()
|
||||
local function exp(x)
|
||||
local res, err = textutils.unserializeJSON(x, { nbt_style = true })
|
||||
if not res then error(err, 2) end
|
||||
return expect(res)
|
||||
end
|
||||
it("basic objects", function()
|
||||
exp([[{ a: 1, b:2 }]]):same { a = 1, b = 2 }
|
||||
end)
|
||||
|
||||
it("suffixed numbers", function()
|
||||
exp("1b"):eq(1)
|
||||
exp("1.1d"):eq(1.1)
|
||||
end)
|
||||
|
||||
it("strings", function()
|
||||
exp("'123'"):eq("123")
|
||||
exp("\"123\""):eq("123")
|
||||
end)
|
||||
|
||||
it("typed arrays", function()
|
||||
exp("[B; 1, 2, 3]"):same { 1, 2, 3 }
|
||||
exp("[B;]"):same {}
|
||||
end)
|
||||
end)
|
||||
|
||||
describe("passes nst/JSONTestSuite", function()
|
||||
local search_path = "test-rom/data/json-parsing"
|
||||
local skip = dofile(search_path .. "/skip.lua")
|
||||
for _, file in pairs(fs.find(search_path .. "/*.json")) do
|
||||
local name = fs.getName(file):sub(1, -6);
|
||||
(skip[name] and pending or it)(name, function()
|
||||
local h = io.open(file, "r")
|
||||
local contents = h:read("*a")
|
||||
h:close()
|
||||
|
||||
local res, err = textutils.unserializeJSON(contents)
|
||||
local kind = fs.getName(file):sub(1, 1)
|
||||
if kind == "n" then
|
||||
expect(res):eq(nil)
|
||||
elseif kind == "y" then
|
||||
if err ~= nil then fail("Expected test to pass, but failed with " .. err) end
|
||||
end
|
||||
end)
|
||||
end
|
||||
end)
|
||||
end)
|
||||
|
||||
describe("textutils.urlEncode", function()
|
||||
|
Reference in New Issue
Block a user