Skip to content

Commit cd879b0

Browse files
authored
Merge pull request #508 from neumond/mc-1.15.x
Fix JSON serialization of strings
2 parents ac7979f + 053cb1b commit cd879b0

File tree

2 files changed

+41
-2
lines changed

2 files changed

+41
-2
lines changed

src/main/resources/data/computercraft/lua/rom/apis/textutils.lua

+27-2
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,31 @@ empty_json_array = mk_tbl("[]", "empty_json_array")
335335
-- @see textutils.unserialiseJSON
336336
json_null = mk_tbl("null", "json_null")
337337

338+
local serializeJSONString
339+
do
340+
local function hexify(c)
341+
return ("\\u00%02X"):format(c:byte())
342+
end
343+
344+
local map = {
345+
["\""] = "\\\"",
346+
["\\"] = "\\\\",
347+
["\b"] = "\\b",
348+
["\f"] = "\\f",
349+
["\n"] = "\\n",
350+
["\r"] = "\\r",
351+
["\t"] = "\\t",
352+
}
353+
for i = 0, 0x1f do
354+
local c = string.char(i)
355+
if map[c] == nil then map[c] = hexify(c) end
356+
end
357+
358+
serializeJSONString = function(s)
359+
return ('"%s"'):format(s:gsub("[\0-\x1f\"\\]", map):gsub("[\x7f-\xff]", hexify))
360+
end
361+
end
362+
338363
local function serializeJSONImpl(t, tTracking, bNBTStyle)
339364
local sType = type(t)
340365
if t == empty_json_array then return "[]"
@@ -361,7 +386,7 @@ local function serializeJSONImpl(t, tTracking, bNBTStyle)
361386
if bNBTStyle then
362387
sEntry = tostring(k) .. ":" .. serializeJSONImpl(v, tTracking, bNBTStyle)
363388
else
364-
sEntry = string.format("%q", k) .. ":" .. serializeJSONImpl(v, tTracking, bNBTStyle)
389+
sEntry = serializeJSONString(k) .. ":" .. serializeJSONImpl(v, tTracking, bNBTStyle)
365390
end
366391
if nObjectSize == 0 then
367392
sObjectResult = sObjectResult .. sEntry
@@ -390,7 +415,7 @@ local function serializeJSONImpl(t, tTracking, bNBTStyle)
390415
end
391416

392417
elseif sType == "string" then
393-
return string.format("%q", t)
418+
return serializeJSONString(t)
394419

395420
elseif sType == "number" or sType == "boolean" then
396421
return tostring(t)

src/test/resources/test-rom/spec/apis/textutils_spec.lua

+14
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,20 @@ describe("The textutils library", function()
7878
it("serializes null", function()
7979
expect(textutils.serializeJSON(textutils.json_null)):eq("null")
8080
end)
81+
82+
it("serializes strings", function()
83+
expect(textutils.serializeJSON('a')):eq('"a"')
84+
expect(textutils.serializeJSON('"')):eq('"\\""')
85+
expect(textutils.serializeJSON('\\')):eq('"\\\\"')
86+
expect(textutils.serializeJSON('/')):eq('"/"')
87+
expect(textutils.serializeJSON('\b')):eq('"\\b"')
88+
expect(textutils.serializeJSON('\n')):eq('"\\n"')
89+
expect(textutils.serializeJSON(string.char(0))):eq('"\\u0000"')
90+
expect(textutils.serializeJSON(string.char(0x0A))):eq('"\\n"')
91+
expect(textutils.serializeJSON(string.char(0x1D))):eq('"\\u001D"')
92+
expect(textutils.serializeJSON(string.char(0x81))):eq('"\\u0081"')
93+
expect(textutils.serializeJSON(string.char(0xFF))):eq('"\\u00FF"')
94+
end)
8195
end)
8296

8397
describe("textutils.unserializeJSON", function()

0 commit comments

Comments
 (0)