jbe/bsw@0: --[[-- jbe/bsw@0: json_string = -- JavaScript code representing the given datum (with quotes, if needed) jbe/bsw@0: encode.json( jbe/bsw@0: obj -- true, false, nil or a number or string jbe/bsw@0: ) jbe/bsw@0: jbe@10: This function encodes any native datatype or atom in JavaScript object notation (JSON). It ensures that the returned string can be safely included in inline scripts both in HTML and XHTML (within CDATA section). jbe@10: jbe@1: TODO: can't distinguish unambiguously between empty object and empty list! jbe/bsw@0: jbe@223: TODO: replace with JSON library jbe@223: jbe/bsw@0: --]]-- jbe/bsw@0: jbe@1: -- TODO: check if numeric representations are JSON compatible jbe@1: jbe/bsw@0: function encode.json(obj) jbe/bsw@0: if obj == nil then jbe/bsw@0: return "null"; jbe/bsw@0: elseif atom.has_type(obj, atom.boolean) then jbe/bsw@0: return tostring(obj) jbe/bsw@0: elseif atom.has_type(obj, atom.number) then jbe/bsw@0: return tostring(obj) jbe@1: elseif type(obj) == "table" then jbe@1: local parts = {} jbe@1: local first = true jbe@1: if #obj > 0 then jbe@1: parts[#parts+1] = "[" jbe@1: for idx, value in ipairs(obj) do jbe@1: if first then jbe@1: first = false jbe@1: else jbe@1: parts[#parts+1] = "," jbe@1: end jbe@1: parts[#parts+1] = tostring(value) jbe@1: end jbe@1: parts[#parts+1] = "]" jbe@1: else jbe@1: parts[#parts+1] = "{" jbe@1: for key, value in pairs(obj) do jbe@1: if first then jbe@1: first = false jbe@1: else jbe@1: parts[#parts+1] = "," jbe@1: end jbe@1: parts[#parts+1] = encode.json(key) jbe@1: parts[#parts+1] = ":" jbe@1: parts[#parts+1] = encode.json(value) jbe@1: end jbe@1: parts[#parts+1] = "}" jbe@1: end jbe@1: return table.concat(parts) jbe/bsw@0: else jbe@10: local str = atom.dump(obj) jbe@10: str = string.gsub(str, ".", jbe@10: function (char) jbe@10: if char == '\r' then return '\\r' end jbe@10: if char == '\n' then return '\\n' end jbe@10: if char == '\\' then return '\\\\' end jbe@10: if char == '"' then return '\\"' end jbe@10: local byte = string.byte(char) jbe@10: if byte < 32 then return string.format("\\u%04x", byte) end jbe@10: end jbe@10: ) jbe@10: str = string.gsub(str, "", "]]\\u003e") jbe@10: return '"' .. str .. '"' jbe/bsw@0: end jbe/bsw@0: end