cosmopolitan
cosmopolitan copied to clipboard
`EncodeJson()` improperly escapes single quotes
In redbean version 2.0.15
when trying to JSON-encode any object that has a string with a single-quote in it the encoder improperly escapes single quotes. This error is shown when using DecodeJson()
and also in some other JSON validators.
Example:
one_string = { "something's amiss" }
json_str = assert(EncodeJson(one_string))
print(json_str) -- output: ["something\'s amiss"]
maybe_one_string = assert(DecodeJson(json_str)) -- error: "invalid escape character"
Indeed. EncodeJson
is using EscapeJsStringLiteral
, which is used to escape JavaScript strings, but \'
is valid in JavaScript things, but not in JSON code (according to rfc7159)[https://datatracker.ietf.org/doc/html/rfc7159#page-8]. We'll either have to add a separate function, or allow kEscapeLiteral
to be passed as a parameter, so EscapeJsStringLiteral
and, let's say, EscapeJsonLiteral
can both use the same function, but pass different kEscapeLiteral
values.
I'm sure @jart can come up with a clean option to handle this.
Thanks @pkulchenko, I appreciate you running down the source of this bug!
For others who may be affected, here's a temporary hack that I'm using to fix JSON strings that are affected and an expanded example from the ticket open comment:
--[[
This is a hack to remove improperly escaped single quotes from the result of
`EncodeJson(...)`.
]]
do
if not __EncodeJson then
Log(kLogDebug, "hacking the system (patching EncodeJson)")
__EncodeJson = EncodeJson
EncodeJson = function(...) return (string.gsub(__EncodeJson(...), "\\?'", "'")) end
end
end
-- example
one_string = { "something's amiss; but this \\'tis not" } -- "\\" should remain untouched
json_str = assert(EncodeJson(one_string)) -- use the normal function name still
print(json_str) -- "["something's amiss; but this \\'tis not"]"
maybe_one_string = assert(DecodeJson(json_str)) -- no error this time
print(maybe_one_string[1]) -- "something's amiss; but this \'tis not"