Vurv78 / qjson.lua

Tiny, quick JSON library for lua.
MIT License
7 stars 0 forks source link

Not parsing new line correctly? #5

Open maroofi opened 3 months ago

maroofi commented 3 months ago

Hi, Here is the lua file:

local json = require("qjson")
a = "v=spf1 include:_netblocks.viacom.com include:_spf.salesforce.com include:spf.protection.outlook.com include:servers.mcsv.net include:stspg-customer.com\ninclude:_spf.google.com include:_spf-customer.tbxnet.com ~all"
print(json.encode({a}))

Running it on bash shows 2 lines while it should be one line. lua s.lua | nl

output: 1 ["v=spf1 include:_netblocks.viacom.com include:_spf.salesforce.com include:spf.protection.outlook.com include:servers.mcsv.net include:stspg-customer.com\ 2 include:_spf.google.com include:_spf-customer.tbxnet.com ~all"]

The problem is that it breaks the line into two lines which I think it's not the normal behavior of the JSON.

what do you think?

Thanks,

Vurv78 commented 2 months ago

Sorry for the delay, barely saw this. Thanks for bringing it to my attention. If you want to get this behavior, you can modify the code a bit, which gives me the same result as JSON.stringify and shouldn't be too much slower, hopefully:

local concat, tostring, format, pairs, type, gsub = table.concat, tostring, string.format, pairs, type, string.gsub

local function isarray(t, len)
    for k in pairs(t) do
        if len == 0 or type(k) ~= "number" then
            return false
        else
            len = len - 1
        end
    end

    return true
end

local ESCAPE = { ["\b"] = "\\b", ["\f"] = "\\f", ["\n"] = "\\n", ["\r"] = "\\r", ["\t"] = "\\t" }

local _encode
local function value(v, buffer, nbuffer)
    local t = type(v)
    if t == "table" then
        return _encode(v, buffer, nbuffer)
    elseif t == "string" then
        buffer[nbuffer + 1] = "\"" .. gsub(v, "[\b\f\n\r\t]", ESCAPE) .. "\""
    else
        buffer[nbuffer + 1] = tostring(v)
    end
    return nbuffer + 1
end

Changes

+local concat, tostring, format, pairs, type, gsub = table.concat, tostring, string.format, pairs, type, string.gsub

+ local ESCAPE = { ["\b"] = "\\b", ["\f"] = "\\f", ["\n"] = "\\n", ["\r"] = "\\r", ["\t"] = "\\t", ['"'] = "\\\"" }

+       buffer[nbuffer + 1] = "\"" .. gsub(v, "[\b\f\n\r\t\"]", ESCAPE) .. "\""

edit: fixed quote escape

Problem is the current implementation relies on string.format's %q option which escapes in a way that lua can recognize, not JSON compliant, which they for some reason chose to use \\\n rather than \\\\n even though most people would use \\\\n in a string.

Would like to benchmark before replacing the inner implementation with this -- but even if it is a little slower it's probably best to merge since %q isn't supported on 5.1 like promised on the readme and to be more compliant.

maroofi commented 2 months ago

100% agree. In my opinion, the correct output is way more important than the speed. You can always work on the optimization part but it's important to make sure the output follows the JSON standard.

I like your library, it's very easy to read and small code. great job! Thanks, Sourena