Advertisement
demon012

json

Jun 20th, 2014
304
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 29.82 KB | None | 0 0
  1. -- -*- coding: utf-8 -*-
  2. --
  3. -- Simple JSON encoding and decoding in pure Lua.
  4. --
  5. -- Copyright 2010-2013 Jeffrey Friedl
  6. -- http://regex.info/blog/
  7. --
  8. -- Latest version: http://regex.info/blog/lua/json
  9. --
  10. -- This code is released under a Creative Commons CC-BY "Attribution" License:
  11. -- http://creativecommons.org/licenses/by/3.0/deed.en_US
  12. --
  13. -- It can be used for any purpose so long as the copyright notice and
  14. -- web-page links above are maintained. Enjoy.
  15. --
  16. local VERSION = 20140418.11  -- version history at end of file
  17. local OBJDEF = { VERSION = VERSION }
  18.  
  19.  
  20. --
  21. -- Simple JSON encoding and decoding in pure Lua.
  22. -- http://www.json.org/
  23. --
  24. --
  25. --   JSON = (loadfile "JSON.lua")() -- one-time load of the routines
  26. --
  27. --   local lua_value = JSON:decode(raw_json_text)
  28. --
  29. --   local raw_json_text    = JSON:encode(lua_table_or_value)
  30. --   local pretty_json_text = JSON:encode_pretty(lua_table_or_value) -- "pretty printed" version for human readability
  31. --
  32. --
  33. -- DECODING
  34. --
  35. --   JSON = (loadfile "JSON.lua")() -- one-time load of the routines
  36. --
  37. --   local lua_value = JSON:decode(raw_json_text)
  38. --
  39. --   If the JSON text is for an object or an array, e.g.
  40. --     { "what": "books", "count": 3 }
  41. --   or
  42. --     [ "Larry", "Curly", "Moe" ]
  43. --
  44. --   the result is a Lua table, e.g.
  45. --     { what = "books", count = 3 }
  46. --   or
  47. --     { "Larry", "Curly", "Moe" }
  48. --
  49. --
  50. --   The encode and decode routines accept an optional second argument, "etc", which is not used
  51. --   during encoding or decoding, but upon error is passed along to error handlers. It can be of any
  52. --   type (including nil).
  53. --
  54. --   With most errors during decoding, this code calls
  55. --
  56. --      JSON:onDecodeError(message, text, location, etc)
  57. --
  58. --   with a message about the error, and if known, the JSON text being parsed and the byte count
  59. --   where the problem was discovered. You can replace the default JSON:onDecodeError() with your
  60. --   own function.
  61. --
  62. --   The default onDecodeError() merely augments the message with data about the text and the
  63. --   location if known (and if a second 'etc' argument had been provided to decode(), its value is
  64. --   tacked onto the message as well), and then calls JSON.assert(), which itself defaults to Lua's
  65. --   built-in assert(), and can also be overridden.
  66. --
  67. --   For example, in an Adobe Lightroom plugin, you might use something like
  68. --
  69. --          function JSON:onDecodeError(message, text, location, etc)
  70. --             LrErrors.throwUserError("Internal Error: invalid JSON data")
  71. --          end
  72. --
  73. --   or even just
  74. --
  75. --          function JSON.assert(message)
  76. --             LrErrors.throwUserError("Internal Error: " .. message)
  77. --          end
  78. --
  79. --   If JSON:decode() is passed a nil, this is called instead:
  80. --
  81. --      JSON:onDecodeOfNilError(message, nil, nil, etc)
  82. --
  83. --   and if JSON:decode() is passed HTML instead of JSON, this is called:
  84. --
  85. --      JSON:onDecodeOfHTMLError(message, text, nil, etc)
  86. --
  87. --   The use of the fourth 'etc' argument allows stronger coordination between decoding and error
  88. --   reporting, especially when you provide your own error-handling routines. Continuing with the
  89. --   the Adobe Lightroom plugin example:
  90. --
  91. --          function JSON:onDecodeError(message, text, location, etc)
  92. --             local note = "Internal Error: invalid JSON data"
  93. --             if type(etc) = 'table' and etc.photo then
  94. --                note = note .. " while processing for " .. etc.photo:getFormattedMetadata('fileName')
  95. --             end
  96. --             LrErrors.throwUserError(note)
  97. --          end
  98. --
  99. --            :
  100. --            :
  101. --
  102. --          for i, photo in ipairs(photosToProcess) do
  103. --               :            
  104. --               :            
  105. --               local data = JSON:decode(someJsonText, { photo = photo })
  106. --               :            
  107. --               :            
  108. --          end
  109. --
  110. --
  111. --
  112. --
  113.  
  114. -- DECODING AND STRICT TYPES
  115. --
  116. --   Because both JSON objects and JSON arrays are converted to Lua tables, it's not normally
  117. --   possible to tell which a JSON type a particular Lua table was derived from, or guarantee
  118. --   decode-encode round-trip equivalency.
  119. --
  120. --   However, if you enable strictTypes, e.g.
  121. --
  122. --      JSON = (loadfile "JSON.lua")() --load the routines
  123. --      JSON.strictTypes = true
  124. --
  125. --   then the Lua table resulting from the decoding of a JSON object or JSON array is marked via Lua
  126. --   metatable, so that when re-encoded with JSON:encode() it ends up as the appropriate JSON type.
  127. --
  128. --   (This is not the default because other routines may not work well with tables that have a
  129. --   metatable set, for example, Lightroom API calls.)
  130. --
  131. --
  132. -- ENCODING
  133. --
  134. --   JSON = (loadfile "JSON.lua")() -- one-time load of the routines
  135. --
  136. --   local raw_json_text    = JSON:encode(lua_table_or_value)
  137. --   local pretty_json_text = JSON:encode_pretty(lua_table_or_value) -- "pretty printed" version for human readability
  138.  
  139. --   On error during encoding, this code calls:
  140. --
  141. --    JSON:onEncodeError(message, etc)
  142. --
  143. --   which you can override in your local JSON object.
  144. --
  145. --   If the Lua table contains both string and numeric keys, it fits neither JSON's
  146. --   idea of an object, nor its idea of an array. To get around this, when any string
  147. --   key exists (or when non-positive numeric keys exist), numeric keys are converted
  148. --   to strings.
  149. --
  150. --   For example,
  151. --     JSON:encode({ "one", "two", "three", SOMESTRING = "some string" }))
  152. --   produces the JSON object
  153. --     {"1":"one","2":"two","3":"three","SOMESTRING":"some string"}
  154. --
  155. --   To prohibit this conversion and instead make it an error condition, set
  156. --      JSON.noKeyConversion = true
  157.  
  158.  
  159. --
  160. -- SUMMARY OF METHODS YOU CAN OVERRIDE IN YOUR LOCAL LUA JSON OBJECT
  161. --
  162. --    assert
  163. --    onDecodeError
  164. --    onDecodeOfNilError
  165. --    onDecodeOfHTMLError
  166. --    onEncodeError
  167. --
  168. --  If you want to create a separate Lua JSON object with its own error handlers,
  169. --  you can reload JSON.lua or use the :new() method.
  170. --
  171. ---------------------------------------------------------------------------
  172.  
  173.  
  174. local author = "-[ JSON.lua package by Jeffrey Friedl (http://regex.info/blog/lua/json), version " .. tostring(VERSION) .. " ]-"
  175. local isArray  = { __tostring = function() return "JSON array"  end }    isArray.__index  = isArray
  176. local isObject = { __tostring = function() return "JSON object" end }    isObject.__index = isObject
  177.  
  178.  
  179. function OBJDEF:newArray(tbl)
  180.    return setmetatable(tbl or {}, isArray)
  181. end
  182.  
  183. function OBJDEF:newObject(tbl)
  184.    return setmetatable(tbl or {}, isObject)
  185. end
  186.  
  187. local function unicode_codepoint_as_utf8(codepoint)
  188.    --
  189.    -- codepoint is a number
  190.    --
  191.    if codepoint <= 127 then
  192.       return string.char(codepoint)
  193.  
  194.    elseif codepoint <= 2047 then
  195.       --
  196.       -- 110yyyxx 10xxxxxx         <-- useful notation from http://en.wikipedia.org/wiki/Utf8
  197.       --
  198.       local highpart = math.floor(codepoint / 0x40)
  199.       local lowpart  = codepoint - (0x40 * highpart)
  200.       return string.char(0xC0 + highpart,
  201.                          0x80 + lowpart)
  202.  
  203.    elseif codepoint <= 65535 then
  204.       --
  205.       -- 1110yyyy 10yyyyxx 10xxxxxx
  206.       --
  207.       local highpart  = math.floor(codepoint / 0x1000)
  208.       local remainder = codepoint - 0x1000 * highpart
  209.       local midpart   = math.floor(remainder / 0x40)
  210.       local lowpart   = remainder - 0x40 * midpart
  211.  
  212.       highpart = 0xE0 + highpart
  213.       midpart  = 0x80 + midpart
  214.       lowpart  = 0x80 + lowpart
  215.  
  216.       --
  217.       -- Check for an invalid character (thanks Andy R. at Adobe).
  218.       -- See table 3.7, page 93, in http://www.unicode.org/versions/Unicode5.2.0/ch03.pdf#G28070
  219.       --
  220.       if ( highpart == 0xE0 and midpart < 0xA0 ) or
  221.          ( highpart == 0xED and midpart > 0x9F ) or
  222.          ( highpart == 0xF0 and midpart < 0x90 ) or
  223.          ( highpart == 0xF4 and midpart > 0x8F )
  224.       then
  225.          return "?"
  226.       else
  227.          return string.char(highpart,
  228.                             midpart,
  229.                             lowpart)
  230.       end
  231.  
  232.    else
  233.       --
  234.       -- 11110zzz 10zzyyyy 10yyyyxx 10xxxxxx
  235.       --
  236.       local highpart  = math.floor(codepoint / 0x40000)
  237.       local remainder = codepoint - 0x40000 * highpart
  238.       local midA      = math.floor(remainder / 0x1000)
  239.       remainder       = remainder - 0x1000 * midA
  240.       local midB      = math.floor(remainder / 0x40)
  241.       local lowpart   = remainder - 0x40 * midB
  242.  
  243.       return string.char(0xF0 + highpart,
  244.                          0x80 + midA,
  245.                          0x80 + midB,
  246.                          0x80 + lowpart)
  247.    end
  248. end
  249.  
  250. function OBJDEF:onDecodeError(message, text, location, etc)
  251.    if text then
  252.       if location then
  253.          message = string.format("%s at char %d of: %s", message, location, text)
  254.       else
  255.          message = string.format("%s: %s", message, text)
  256.       end
  257.    end
  258.  
  259.    if etc ~= nil then
  260.       message = message .. " (" .. OBJDEF:encode(etc) .. ")"
  261.    end
  262.  
  263.    if self.assert then
  264.       self.assert(false, message)
  265.    else
  266.       assert(false, message)
  267.    end
  268. end
  269.  
  270. OBJDEF.onDecodeOfNilError  = OBJDEF.onDecodeError
  271. OBJDEF.onDecodeOfHTMLError = OBJDEF.onDecodeError
  272.  
  273. function OBJDEF:onEncodeError(message, etc)
  274.    if etc ~= nil then
  275.       message = message .. " (" .. OBJDEF:encode(etc) .. ")"
  276.    end
  277.  
  278.    if self.assert then
  279.       self.assert(false, message)
  280.    else
  281.       assert(false, message)
  282.    end
  283. end
  284.  
  285. local function grok_number(self, text, start, etc)
  286.    --
  287.    -- Grab the integer part
  288.    --
  289.    local integer_part = text:match('^-?[1-9]%d*', start)
  290.                      or text:match("^-?0",        start)
  291.  
  292.    if not integer_part then
  293.       self:onDecodeError("expected number", text, start, etc)
  294.    end
  295.  
  296.    local i = start + integer_part:len()
  297.  
  298.    --
  299.    -- Grab an optional decimal part
  300.    --
  301.    local decimal_part = text:match('^%.%d+', i) or ""
  302.  
  303.    i = i + decimal_part:len()
  304.  
  305.    --
  306.    -- Grab an optional exponential part
  307.    --
  308.    local exponent_part = text:match('^[eE][-+]?%d+', i) or ""
  309.  
  310.    i = i + exponent_part:len()
  311.  
  312.    local full_number_text = integer_part .. decimal_part .. exponent_part
  313.    local as_number = tonumber(full_number_text)
  314.  
  315.    if not as_number then
  316.       self:onDecodeError("bad number", text, start, etc)
  317.    end
  318.  
  319.    return as_number, i
  320. end
  321.  
  322.  
  323. local function grok_string(self, text, start, etc)
  324.  
  325.    if text:sub(start,start) ~= '"' then
  326.       self:onDecodeError("expected string's opening quote", text, start, etc)
  327.    end
  328.  
  329.    local i = start + 1 -- +1 to bypass the initial quote
  330.    local text_len = text:len()
  331.    local VALUE = ""
  332.    while i <= text_len do
  333.       local c = text:sub(i,i)
  334.       if c == '"' then
  335.          return VALUE, i + 1
  336.       end
  337.       if c ~= '\\' then
  338.          VALUE = VALUE .. c
  339.          i = i + 1
  340.       elseif text:match('^\\b', i) then
  341.          VALUE = VALUE .. "\b"
  342.          i = i + 2
  343.       elseif text:match('^\\f', i) then
  344.          VALUE = VALUE .. "\f"
  345.          i = i + 2
  346.       elseif text:match('^\\n', i) then
  347.          VALUE = VALUE .. "\n"
  348.          i = i + 2
  349.       elseif text:match('^\\r', i) then
  350.          VALUE = VALUE .. "\r"
  351.          i = i + 2
  352.       elseif text:match('^\\t', i) then
  353.          VALUE = VALUE .. "\t"
  354.          i = i + 2
  355.       else
  356.          local hex = text:match('^\\u([0123456789aAbBcCdDeEfF][0123456789aAbBcCdDeEfF][0123456789aAbBcCdDeEfF][0123456789aAbBcCdDeEfF])', i)
  357.          if hex then
  358.             i = i + 6 -- bypass what we just read
  359.  
  360.             -- We have a Unicode codepoint. It could be standalone, or if in the proper range and
  361.             -- followed by another in a specific range, it'll be a two-code surrogate pair.
  362.             local codepoint = tonumber(hex, 16)
  363.             if codepoint >= 0xD800 and codepoint <= 0xDBFF then
  364.                -- it's a hi surrogate... see whether we have a following low
  365.                local lo_surrogate = text:match('^\\u([dD][cdefCDEF][0123456789aAbBcCdDeEfF][0123456789aAbBcCdDeEfF])', i)
  366.                if lo_surrogate then
  367.                   i = i + 6 -- bypass the low surrogate we just read
  368.                   codepoint = 0x2400 + (codepoint - 0xD800) * 0x400 + tonumber(lo_surrogate, 16)
  369.                else
  370.                   -- not a proper low, so we'll just leave the first codepoint as is and spit it out.
  371.                end
  372.             end
  373.             VALUE = VALUE .. unicode_codepoint_as_utf8(codepoint)
  374.  
  375.          else
  376.  
  377.             -- just pass through what's escaped
  378.             VALUE = VALUE .. text:match('^\\(.)', i)
  379.             i = i + 2
  380.          end
  381.       end
  382.    end
  383.  
  384.    self:onDecodeError("unclosed string", text, start, etc)
  385. end
  386.  
  387. local function skip_whitespace(text, start)
  388.  
  389.    local match_start, match_end = text:find("^[ \n\r\t]+", start) -- [http://www.ietf.org/rfc/rfc4627.txt] Section 2
  390.    if match_end then
  391.       return match_end + 1
  392.    else
  393.       return start
  394.    end
  395. end
  396.  
  397. local grok_one -- assigned later
  398.  
  399. local function grok_object(self, text, start, etc)
  400.    if not text:sub(start,start) == '{' then
  401.       self:onDecodeError("expected '{'", text, start, etc)
  402.    end
  403.  
  404.    local i = skip_whitespace(text, start + 1) -- +1 to skip the '{'
  405.  
  406.    local VALUE = self.strictTypes and self:newObject { } or { }
  407.  
  408.    if text:sub(i,i) == '}' then
  409.       return VALUE, i + 1
  410.    end
  411.    local text_len = text:len()
  412.    while i <= text_len do
  413.       local key, new_i = grok_string(self, text, i, etc)
  414.  
  415.       i = skip_whitespace(text, new_i)
  416.  
  417.       if text:sub(i, i) ~= ':' then
  418.          self:onDecodeError("expected colon", text, i, etc)
  419.       end
  420.  
  421.       i = skip_whitespace(text, i + 1)
  422.  
  423.       local val, new_i = grok_one(self, text, i)
  424.  
  425.       VALUE[key] = val
  426.  
  427.       --
  428.       -- Expect now either '}' to end things, or a ',' to allow us to continue.
  429.       --
  430.       i = skip_whitespace(text, new_i)
  431.  
  432.       local c = text:sub(i,i)
  433.  
  434.       if c == '}' then
  435.          return VALUE, i + 1
  436.       end
  437.  
  438.       if text:sub(i, i) ~= ',' then
  439.          self:onDecodeError("expected comma or '}'", text, i, etc)
  440.       end
  441.  
  442.       i = skip_whitespace(text, i + 1)
  443.    end
  444.  
  445.    self:onDecodeError("unclosed '{'", text, start, etc)
  446. end
  447.  
  448. local function grok_array(self, text, start, etc)
  449.    if not text:sub(start,start) == '[' then
  450.       self:onDecodeError("expected '['", text, start, etc)
  451.    end
  452.  
  453.    local i = skip_whitespace(text, start + 1) -- +1 to skip the '['
  454.    local VALUE = self.strictTypes and self:newArray { } or { }
  455.    if text:sub(i,i) == ']' then
  456.       return VALUE, i + 1
  457.    end
  458.  
  459.    local VALUE_INDEX = 1
  460.  
  461.    local text_len = text:len()
  462.    while i <= text_len do
  463.       local val, new_i = grok_one(self, text, i)
  464.  
  465.       -- can't table.insert(VALUE, val) here because it's a no-op if val is nil
  466.       VALUE[VALUE_INDEX] = val
  467.       VALUE_INDEX = VALUE_INDEX + 1
  468.  
  469.       i = skip_whitespace(text, new_i)
  470.  
  471.       --
  472.       -- Expect now either ']' to end things, or a ',' to allow us to continue.
  473.       --
  474.       local c = text:sub(i,i)
  475.       if c == ']' then
  476.          return VALUE, i + 1
  477.       end
  478.       if text:sub(i, i) ~= ',' then
  479.          self:onDecodeError("expected comma or '['", text, i, etc)
  480.       end
  481.       i = skip_whitespace(text, i + 1)
  482.    end
  483.    self:onDecodeError("unclosed '['", text, start, etc)
  484. end
  485.  
  486.  
  487. grok_one = function(self, text, start, etc)
  488.    -- Skip any whitespace
  489.    start = skip_whitespace(text, start)
  490.  
  491.    if start > text:len() then
  492.       self:onDecodeError("unexpected end of string", text, nil, etc)
  493.    end
  494.  
  495.    if text:find('^"', start) then
  496.       return grok_string(self, text, start, etc)
  497.  
  498.    elseif text:find('^[-0123456789 ]', start) then
  499.       return grok_number(self, text, start, etc)
  500.  
  501.    elseif text:find('^%{', start) then
  502.       return grok_object(self, text, start, etc)
  503.  
  504.    elseif text:find('^%[', start) then
  505.       return grok_array(self, text, start, etc)
  506.  
  507.    elseif text:find('^true', start) then
  508.       return true, start + 4
  509.  
  510.    elseif text:find('^false', start) then
  511.       return false, start + 5
  512.  
  513.    elseif text:find('^null', start) then
  514.       return nil, start + 4
  515.  
  516.    else
  517.       self:onDecodeError("can't parse JSON", text, start, etc)
  518.    end
  519. end
  520.  
  521. function OBJDEF:decode(text, etc)
  522.    if type(self) ~= 'table' or self.__index ~= OBJDEF then
  523.       OBJDEF:onDecodeError("JSON:decode must be called in method format", nil, nil, etc)
  524.    end
  525.  
  526.    if text == nil then
  527.       self:onDecodeOfNilError(string.format("nil passed to JSON:decode()"), nil, nil, etc)
  528.    elseif type(text) ~= 'string' then
  529.       self:onDecodeError(string.format("expected string argument to JSON:decode(), got %s", type(text)), nil, nil, etc)
  530.    end
  531.  
  532.    if text:match('^%s*$') then
  533.       return nil
  534.    end
  535.  
  536.    if text:match('^%s*<') then
  537.       -- Can't be JSON... we'll assume it's HTML
  538.       self:onDecodeOfHTMLError(string.format("html passed to JSON:decode()"), text, nil, etc)
  539.    end
  540.  
  541.    --
  542.    -- Ensure that it's not UTF-32 or UTF-16.
  543.    -- Those are perfectly valid encodings for JSON (as per RFC 4627 section 3),
  544.    -- but this package can't handle them.
  545.    --
  546.    if text:sub(1,1):byte() == 0 or (text:len() >= 2 and text:sub(2,2):byte() == 0) then
  547.       self:onDecodeError("JSON package groks only UTF-8, sorry", text, nil, etc)
  548.    end
  549.  
  550.    local success, value = pcall(grok_one, self, text, 1, etc)
  551.  
  552.    if success then
  553.       return value
  554.    else
  555.       -- if JSON:onDecodeError() didn't abort out of the pcall, we'll have received the error message here as "value", so pass it along as an assert.
  556.       if self.assert then
  557.          self.assert(false, value)
  558.       else
  559.          assert(false, value)
  560.       end
  561.       -- and if we're still here, return a nil and throw the error message on as a second arg
  562.       return nil, value
  563.    end
  564. end
  565.  
  566. local function backslash_replacement_function(c)
  567.    if c == "\n" then
  568.       return "\\n"
  569.    elseif c == "\r" then
  570.       return "\\r"
  571.    elseif c == "\t" then
  572.       return "\\t"
  573.    elseif c == "\b" then
  574.       return "\\b"
  575.    elseif c == "\f" then
  576.       return "\\f"
  577.    elseif c == '"' then
  578.       return '\\"'
  579.    elseif c == '\\' then
  580.       return '\\\\'
  581.    else
  582.       return string.format("\\u%04x", c:byte())
  583.    end
  584. end
  585.  
  586. local chars_to_be_escaped_in_JSON_string
  587.    = '['
  588.    ..    '"'    -- class sub-pattern to match a double quote
  589.    ..    '%\\'  -- class sub-pattern to match a backslash
  590.    ..    '%z'   -- class sub-pattern to match a null
  591.    ..    '\001' .. '-' .. '\031' -- class sub-pattern to match control characters
  592.    .. ']'
  593.  
  594. local function json_string_literal(value)
  595.    local newval = value:gsub(chars_to_be_escaped_in_JSON_string, backslash_replacement_function)
  596.    return '"' .. newval .. '"'
  597. end
  598.  
  599. local function object_or_array(self, T, etc)
  600.    --
  601.    -- We need to inspect all the keys... if there are any strings, we'll convert to a JSON
  602.    -- object. If there are only numbers, it's a JSON array.
  603.    --
  604.    -- If we'll be converting to a JSON object, we'll want to sort the keys so that the
  605.    -- end result is deterministic.
  606.    --
  607.    local string_keys = { }
  608.    local number_keys = { }
  609.    local number_keys_must_be_strings = false
  610.    local maximum_number_key
  611.  
  612.    for key in pairs(T) do
  613.       if type(key) == 'string' then
  614.          table.insert(string_keys, key)
  615.       elseif type(key) == 'number' then
  616.          table.insert(number_keys, key)
  617.          if key <= 0 or key >= math.huge then
  618.             number_keys_must_be_strings = true
  619.          elseif not maximum_number_key or key > maximum_number_key then
  620.             maximum_number_key = key
  621.          end
  622.       else
  623.          self:onEncodeError("can't encode table with a key of type " .. type(key), etc)
  624.       end
  625.    end
  626.  
  627.    if #string_keys == 0 and not number_keys_must_be_strings then
  628.       --
  629.       -- An empty table, or a numeric-only array
  630.       --
  631.       if #number_keys > 0 then
  632.          return nil, maximum_number_key -- an array
  633.       elseif tostring(T) == "JSON array" then
  634.          return nil
  635.       elseif tostring(T) == "JSON object" then
  636.          return { }
  637.       else
  638.          -- have to guess, so we'll pick array, since empty arrays are likely more common than empty objects
  639.          return nil
  640.       end
  641.    end
  642.  
  643.    table.sort(string_keys)
  644.  
  645.    local map
  646.    if #number_keys > 0 then
  647.       --
  648.       -- If we're here then we have either mixed string/number keys, or numbers inappropriate for a JSON array
  649.       -- It's not ideal, but we'll turn the numbers into strings so that we can at least create a JSON object.
  650.       --
  651.  
  652.       if JSON.noKeyConversion then
  653.          self:onEncodeError("a table with both numeric and string keys could be an object or array; aborting", etc)
  654.       end
  655.  
  656.       --
  657.       -- Have to make a shallow copy of the source table so we can remap the numeric keys to be strings
  658.       --
  659.       map = { }
  660.       for key, val in pairs(T) do
  661.          map[key] = val
  662.       end
  663.  
  664.       table.sort(number_keys)
  665.  
  666.       --
  667.       -- Throw numeric keys in there as strings
  668.       --
  669.       for _, number_key in ipairs(number_keys) do
  670.          local string_key = tostring(number_key)
  671.          if map[string_key] == nil then
  672.             table.insert(string_keys , string_key)
  673.             map[string_key] = T[number_key]
  674.          else
  675.             self:onEncodeError("conflict converting table with mixed-type keys into a JSON object: key " .. number_key .. " exists both as a string and a number.", etc)
  676.          end
  677.       end
  678.    end
  679.  
  680.    return string_keys, nil, map
  681. end
  682.  
  683. --
  684. -- Encode
  685. --
  686. local encode_value -- must predeclare because it calls itself
  687. function encode_value(self, value, parents, etc, indent) -- non-nil indent means pretty-printing
  688.  
  689.    if value == nil then
  690.       return 'null'
  691.  
  692.    elseif type(value) == 'string' then
  693.       return json_string_literal(value)
  694.  
  695.    elseif type(value) == 'number' then
  696.       if value ~= value then
  697.          --
  698.          -- NaN (Not a Number).
  699.          -- JSON has no NaN, so we have to fudge the best we can. This should really be a package option.
  700.          --
  701.          return "null"
  702.       elseif value >= math.huge then
  703.          --
  704.          -- Positive infinity. JSON has no INF, so we have to fudge the best we can. This should
  705.          -- really be a package option. Note: at least with some implementations, positive infinity
  706.          -- is both ">= math.huge" and "<= -math.huge", which makes no sense but that's how it is.
  707.          -- Negative infinity is properly "<= -math.huge". So, we must be sure to check the ">="
  708.          -- case first.
  709.          --
  710.          return "1e+9999"
  711.       elseif value <= -math.huge then
  712.          --
  713.          -- Negative infinity.
  714.          -- JSON has no INF, so we have to fudge the best we can. This should really be a package option.
  715.          --
  716.          return "-1e+9999"
  717.       else
  718.          return tostring(value)
  719.       end
  720.  
  721.    elseif type(value) == 'boolean' then
  722.       return tostring(value)
  723.  
  724.    elseif type(value) ~= 'table' then
  725.       self:onEncodeError("can't convert " .. type(value) .. " to JSON", etc)
  726.  
  727.    else
  728.       --
  729.       -- A table to be converted to either a JSON object or array.
  730.       --
  731.       local T = value
  732.  
  733.       if parents[T] then
  734.          self:onEncodeError("table " .. tostring(T) .. " is a child of itself", etc)
  735.       else
  736.          parents[T] = true
  737.       end
  738.  
  739.       local result_value
  740.  
  741.       local object_keys, maximum_number_key, map = object_or_array(self, T, etc)
  742.       if maximum_number_key then
  743.          --
  744.          -- An array...
  745.          --
  746.          local ITEMS = { }
  747.          for i = 1, maximum_number_key do
  748.             table.insert(ITEMS, encode_value(self, T[i], parents, etc, indent))
  749.          end
  750.  
  751.          if indent then
  752.             result_value = "[ " .. table.concat(ITEMS, ", ") .. " ]"
  753.          else
  754.             result_value = "[" .. table.concat(ITEMS, ",") .. "]"
  755.          end
  756.  
  757.       elseif object_keys then
  758.          --
  759.          -- An object
  760.          --
  761.          local TT = map or T
  762.  
  763.          if indent then
  764.  
  765.             local KEYS = { }
  766.             local max_key_length = 0
  767.             for _, key in ipairs(object_keys) do
  768.                local encoded = encode_value(self, tostring(key), parents, etc, "")
  769.                max_key_length = math.max(max_key_length, #encoded)
  770.                table.insert(KEYS, encoded)
  771.             end
  772.             local key_indent = indent .. "    "
  773.             local subtable_indent = indent .. string.rep(" ", max_key_length + 2 + 4)
  774.             local FORMAT = "%s%" .. string.format("%d", max_key_length) .. "s: %s"
  775.  
  776.             local COMBINED_PARTS = { }
  777.             for i, key in ipairs(object_keys) do
  778.                local encoded_val = encode_value(self, TT[key], parents, etc, subtable_indent)
  779.                table.insert(COMBINED_PARTS, string.format(FORMAT, key_indent, KEYS[i], encoded_val))
  780.             end
  781.             result_value = "{\n" .. table.concat(COMBINED_PARTS, ",\n") .. "\n" .. indent .. "}"
  782.  
  783.          else
  784.  
  785.             local PARTS = { }
  786.             for _, key in ipairs(object_keys) do
  787.                local encoded_val = encode_value(self, TT[key],       parents, etc, indent)
  788.                local encoded_key = encode_value(self, tostring(key), parents, etc, indent)
  789.                table.insert(PARTS, string.format("%s:%s", encoded_key, encoded_val))
  790.             end
  791.             result_value = "{" .. table.concat(PARTS, ",") .. "}"
  792.  
  793.          end
  794.       else
  795.          --
  796.          -- An empty array/object... we'll treat it as an array, though it should really be an option
  797.          --
  798.          result_value = "[]"
  799.       end
  800.  
  801.       parents[T] = false
  802.       return result_value
  803.    end
  804. end
  805.  
  806.  
  807. function OBJDEF:encode(value, etc)
  808.    if type(self) ~= 'table' or self.__index ~= OBJDEF then
  809.       OBJDEF:onEncodeError("JSON:encode must be called in method format", etc)
  810.    end
  811.    return encode_value(self, value, {}, etc, nil)
  812. end
  813.  
  814. function OBJDEF:encode_pretty(value, etc)
  815.    if type(self) ~= 'table' or self.__index ~= OBJDEF then
  816.       OBJDEF:onEncodeError("JSON:encode_pretty must be called in method format", etc)
  817.    end
  818.    return encode_value(self, value, {}, etc, "")
  819. end
  820.  
  821. function OBJDEF.__tostring()
  822.    return "JSON encode/decode package"
  823. end
  824.  
  825. OBJDEF.__index = OBJDEF
  826.  
  827. function OBJDEF:new(args)
  828.    local new = { }
  829.  
  830.    if args then
  831.       for key, val in pairs(args) do
  832.          new[key] = val
  833.       end
  834.    end
  835.  
  836.    return setmetatable(new, OBJDEF)
  837. end
  838.  
  839. return OBJDEF:new()
  840.  
  841. --
  842. -- Version history:
  843. --
  844. --   20140418.11   JSON nulls embedded within an array were being ignored, such that
  845. --                     ["1",null,null,null,null,null,"seven"],
  846. --                 would return
  847. --                     {1,"seven"}
  848. --                 It's now fixed to properly return
  849. --                     {1, nil, nil, nil, nil, nil, "seven"}
  850. --                 Thanks to "haddock" for catching the error.
  851. --
  852. --   20140116.10   The user's JSON.assert() wasn't always being used. Thanks to "blue" for the heads up.
  853. --
  854. --   20131118.9    Update for Lua 5.3... it seems that tostring(2/1) produces "2.0" instead of "2",
  855. --                 and this caused some problems.
  856. --
  857. --   20131031.8    Unified the code for encode() and encode_pretty(); they had been stupidly separate,
  858. --                 and had of course diverged (encode_pretty didn't get the fixes that encode got, so
  859. --                 sometimes produced incorrect results; thanks to Mattie for the heads up).
  860. --
  861. --                 Handle encoding tables with non-positive numeric keys (unlikely, but possible).
  862. --
  863. --                 If a table has both numeric and string keys, or its numeric keys are inappropriate
  864. --                 (such as being non-positive or infinite), the numeric keys are turned into
  865. --                 string keys appropriate for a JSON object. So, as before,
  866. --                         JSON:encode({ "one", "two", "three" })
  867. --                 produces the array
  868. --                         ["one","two","three"]
  869. --                 but now something with mixed key types like
  870. --                         JSON:encode({ "one", "two", "three", SOMESTRING = "some string" }))
  871. --                 instead of throwing an error produces an object:
  872. --                         {"1":"one","2":"two","3":"three","SOMESTRING":"some string"}
  873. --
  874. --                 To maintain the prior throw-an-error semantics, set
  875. --                      JSON.noKeyConversion = true
  876. --                
  877. --   20131004.7    Release under a Creative Commons CC-BY license, which I should have done from day one, sorry.
  878. --
  879. --   20130120.6    Comment update: added a link to the specific page on my blog where this code can
  880. --                 be found, so that folks who come across the code outside of my blog can find updates
  881. --                 more easily.
  882. --
  883. --   20111207.5    Added support for the 'etc' arguments, for better error reporting.
  884. --
  885. --   20110731.4    More feedback from David Kolf on how to make the tests for Nan/Infinity system independent.
  886. --
  887. --   20110730.3    Incorporated feedback from David Kolf at http://lua-users.org/wiki/JsonModules:
  888. --
  889. --                   * When encoding lua for JSON, Sparse numeric arrays are now handled by
  890. --                     spitting out full arrays, such that
  891. --                        JSON:encode({"one", "two", [10] = "ten"})
  892. --                     returns
  893. --                        ["one","two",null,null,null,null,null,null,null,"ten"]
  894. --
  895. --                     In 20100810.2 and earlier, only up to the first non-null value would have been retained.
  896. --
  897. --                   * When encoding lua for JSON, numeric value NaN gets spit out as null, and infinity as "1+e9999".
  898. --                     Version 20100810.2 and earlier created invalid JSON in both cases.
  899. --
  900. --                   * Unicode surrogate pairs are now detected when decoding JSON.
  901. --
  902. --   20100810.2    added some checking to ensure that an invalid Unicode character couldn't leak in to the UTF-8 encoding
  903. --
  904. --   20100731.1    initial public release
  905. --
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement