JSON.lua
changeset 0 d7ee4e2ed49d
equal deleted inserted replaced
-1:000000000000 0:d7ee4e2ed49d
       
     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 = 20131118.9  -- 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    if etc ~= nil then
       
   259       message = message .. " (" .. OBJDEF:encode(etc) .. ")"
       
   260    end
       
   261 
       
   262    if self.assert then
       
   263       self.assert(false, message)
       
   264    else
       
   265       assert(false, message)
       
   266    end
       
   267 end
       
   268 
       
   269 OBJDEF.onDecodeOfNilError  = OBJDEF.onDecodeError
       
   270 OBJDEF.onDecodeOfHTMLError = OBJDEF.onDecodeError
       
   271 
       
   272 function OBJDEF:onEncodeError(message, etc)
       
   273    if etc ~= nil then
       
   274       message = message .. " (" .. OBJDEF:encode(etc) .. ")"
       
   275    end
       
   276 
       
   277    if self.assert then
       
   278       self.assert(false, message)
       
   279    else
       
   280       assert(false, message)
       
   281    end
       
   282 end
       
   283 
       
   284 local function grok_number(self, text, start, etc)
       
   285    --
       
   286    -- Grab the integer part
       
   287    --
       
   288    local integer_part = text:match('^-?[1-9]%d*', start)
       
   289                      or text:match("^-?0",        start)
       
   290 
       
   291    if not integer_part then
       
   292       self:onDecodeError("expected number", text, start, etc)
       
   293    end
       
   294 
       
   295    local i = start + integer_part:len()
       
   296 
       
   297    --
       
   298    -- Grab an optional decimal part
       
   299    --
       
   300    local decimal_part = text:match('^%.%d+', i) or ""
       
   301 
       
   302    i = i + decimal_part:len()
       
   303 
       
   304    --
       
   305    -- Grab an optional exponential part
       
   306    --
       
   307    local exponent_part = text:match('^[eE][-+]?%d+', i) or ""
       
   308 
       
   309    i = i + exponent_part:len()
       
   310 
       
   311    local full_number_text = integer_part .. decimal_part .. exponent_part
       
   312    local as_number = tonumber(full_number_text)
       
   313 
       
   314    if not as_number then
       
   315       self:onDecodeError("bad number", text, start, etc)
       
   316    end
       
   317 
       
   318    return as_number, i
       
   319 end
       
   320 
       
   321 
       
   322 local function grok_string(self, text, start, etc)
       
   323 
       
   324    if text:sub(start,start) ~= '"' then
       
   325       self:onDecodeError("expected string's opening quote", text, start, etc)
       
   326    end
       
   327 
       
   328    local i = start + 1 -- +1 to bypass the initial quote
       
   329    local text_len = text:len()
       
   330    local VALUE = ""
       
   331    while i <= text_len do
       
   332       local c = text:sub(i,i)
       
   333       if c == '"' then
       
   334          return VALUE, i + 1
       
   335       end
       
   336       if c ~= '\\' then
       
   337          VALUE = VALUE .. c
       
   338          i = i + 1
       
   339       elseif text:match('^\\b', i) then
       
   340          VALUE = VALUE .. "\b"
       
   341          i = i + 2
       
   342       elseif text:match('^\\f', i) then
       
   343          VALUE = VALUE .. "\f"
       
   344          i = i + 2
       
   345       elseif text:match('^\\n', i) then
       
   346          VALUE = VALUE .. "\n"
       
   347          i = i + 2
       
   348       elseif text:match('^\\r', i) then
       
   349          VALUE = VALUE .. "\r"
       
   350          i = i + 2
       
   351       elseif text:match('^\\t', i) then
       
   352          VALUE = VALUE .. "\t"
       
   353          i = i + 2
       
   354       else
       
   355          local hex = text:match('^\\u([0123456789aAbBcCdDeEfF][0123456789aAbBcCdDeEfF][0123456789aAbBcCdDeEfF][0123456789aAbBcCdDeEfF])', i)
       
   356          if hex then
       
   357             i = i + 6 -- bypass what we just read
       
   358 
       
   359             -- We have a Unicode codepoint. It could be standalone, or if in the proper range and
       
   360             -- followed by another in a specific range, it'll be a two-code surrogate pair.
       
   361             local codepoint = tonumber(hex, 16)
       
   362             if codepoint >= 0xD800 and codepoint <= 0xDBFF then
       
   363                -- it's a hi surrogate... see whether we have a following low
       
   364                local lo_surrogate = text:match('^\\u([dD][cdefCDEF][0123456789aAbBcCdDeEfF][0123456789aAbBcCdDeEfF])', i)
       
   365                if lo_surrogate then
       
   366                   i = i + 6 -- bypass the low surrogate we just read
       
   367                   codepoint = 0x2400 + (codepoint - 0xD800) * 0x400 + tonumber(lo_surrogate, 16)
       
   368                else
       
   369                   -- not a proper low, so we'll just leave the first codepoint as is and spit it out.
       
   370                end
       
   371             end
       
   372             VALUE = VALUE .. unicode_codepoint_as_utf8(codepoint)
       
   373 
       
   374          else
       
   375 
       
   376             -- just pass through what's escaped
       
   377             VALUE = VALUE .. text:match('^\\(.)', i)
       
   378             i = i + 2
       
   379          end
       
   380       end
       
   381    end
       
   382 
       
   383    self:onDecodeError("unclosed string", text, start, etc)
       
   384 end
       
   385 
       
   386 local function skip_whitespace(text, start)
       
   387 
       
   388    local match_start, match_end = text:find("^[ \n\r\t]+", start) -- [http://www.ietf.org/rfc/rfc4627.txt] Section 2
       
   389    if match_end then
       
   390       return match_end + 1
       
   391    else
       
   392       return start
       
   393    end
       
   394 end
       
   395 
       
   396 local grok_one -- assigned later
       
   397 
       
   398 local function grok_object(self, text, start, etc)
       
   399    if not text:sub(start,start) == '{' then
       
   400       self:onDecodeError("expected '{'", text, start, etc)
       
   401    end
       
   402 
       
   403    local i = skip_whitespace(text, start + 1) -- +1 to skip the '{'
       
   404 
       
   405    local VALUE = self.strictTypes and self:newObject { } or { }
       
   406 
       
   407    if text:sub(i,i) == '}' then
       
   408       return VALUE, i + 1
       
   409    end
       
   410    local text_len = text:len()
       
   411    while i <= text_len do
       
   412       local key, new_i = grok_string(self, text, i, etc)
       
   413 
       
   414       i = skip_whitespace(text, new_i)
       
   415 
       
   416       if text:sub(i, i) ~= ':' then
       
   417          self:onDecodeError("expected colon", text, i, etc)
       
   418       end
       
   419 
       
   420       i = skip_whitespace(text, i + 1)
       
   421 
       
   422       local val, new_i = grok_one(self, text, i)
       
   423 
       
   424       VALUE[key] = val
       
   425 
       
   426       --
       
   427       -- Expect now either '}' to end things, or a ',' to allow us to continue.
       
   428       --
       
   429       i = skip_whitespace(text, new_i)
       
   430 
       
   431       local c = text:sub(i,i)
       
   432 
       
   433       if c == '}' then
       
   434          return VALUE, i + 1
       
   435       end
       
   436 
       
   437       if text:sub(i, i) ~= ',' then
       
   438          self:onDecodeError("expected comma or '}'", text, i, etc)
       
   439       end
       
   440 
       
   441       i = skip_whitespace(text, i + 1)
       
   442    end
       
   443 
       
   444    self:onDecodeError("unclosed '{'", text, start, etc)
       
   445 end
       
   446 
       
   447 local function grok_array(self, text, start, etc)
       
   448    if not text:sub(start,start) == '[' then
       
   449       self:onDecodeError("expected '['", text, start, etc)
       
   450    end
       
   451 
       
   452    local i = skip_whitespace(text, start + 1) -- +1 to skip the '['
       
   453    local VALUE = self.strictTypes and self:newArray { } or { }
       
   454    if text:sub(i,i) == ']' then
       
   455       return VALUE, i + 1
       
   456    end
       
   457 
       
   458    local text_len = text:len()
       
   459    while i <= text_len do
       
   460       local val, new_i = grok_one(self, text, i)
       
   461 
       
   462       table.insert(VALUE, val)
       
   463 
       
   464       i = skip_whitespace(text, new_i)
       
   465 
       
   466       --
       
   467       -- Expect now either ']' to end things, or a ',' to allow us to continue.
       
   468       --
       
   469       local c = text:sub(i,i)
       
   470       if c == ']' then
       
   471          return VALUE, i + 1
       
   472       end
       
   473       if text:sub(i, i) ~= ',' then
       
   474          self:onDecodeError("expected comma or '['", text, i, etc)
       
   475       end
       
   476       i = skip_whitespace(text, i + 1)
       
   477    end
       
   478    self:onDecodeError("unclosed '['", text, start, etc)
       
   479 end
       
   480 
       
   481 
       
   482 grok_one = function(self, text, start, etc)
       
   483    -- Skip any whitespace
       
   484    start = skip_whitespace(text, start)
       
   485 
       
   486    if start > text:len() then
       
   487       self:onDecodeError("unexpected end of string", text, nil, etc)
       
   488    end
       
   489 
       
   490    if text:find('^"', start) then
       
   491       return grok_string(self, text, start, etc)
       
   492 
       
   493    elseif text:find('^[-0123456789 ]', start) then
       
   494       return grok_number(self, text, start, etc)
       
   495 
       
   496    elseif text:find('^%{', start) then
       
   497       return grok_object(self, text, start, etc)
       
   498 
       
   499    elseif text:find('^%[', start) then
       
   500       return grok_array(self, text, start, etc)
       
   501 
       
   502    elseif text:find('^true', start) then
       
   503       return true, start + 4
       
   504 
       
   505    elseif text:find('^false', start) then
       
   506       return false, start + 5
       
   507 
       
   508    elseif text:find('^null', start) then
       
   509       return nil, start + 4
       
   510 
       
   511    else
       
   512       self:onDecodeError("can't parse JSON", text, start, etc)
       
   513    end
       
   514 end
       
   515 
       
   516 function OBJDEF:decode(text, etc)
       
   517    if type(self) ~= 'table' or self.__index ~= OBJDEF then
       
   518       OBJDEF:onDecodeError("JSON:decode must be called in method format", nil, nil, etc)
       
   519    end
       
   520 
       
   521    if text == nil then
       
   522       self:onDecodeOfNilError(string.format("nil passed to JSON:decode()"), nil, nil, etc)
       
   523    elseif type(text) ~= 'string' then
       
   524       self:onDecodeError(string.format("expected string argument to JSON:decode(), got %s", type(text)), nil, nil, etc)
       
   525    end
       
   526 
       
   527    if text:match('^%s*$') then
       
   528       return nil
       
   529    end
       
   530 
       
   531    if text:match('^%s*<') then
       
   532       -- Can't be JSON... we'll assume it's HTML
       
   533       self:onDecodeOfHTMLError(string.format("html passed to JSON:decode()"), text, nil, etc)
       
   534    end
       
   535 
       
   536    --
       
   537    -- Ensure that it's not UTF-32 or UTF-16.
       
   538    -- Those are perfectly valid encodings for JSON (as per RFC 4627 section 3),
       
   539    -- but this package can't handle them.
       
   540    --
       
   541    if text:sub(1,1):byte() == 0 or (text:len() >= 2 and text:sub(2,2):byte() == 0) then
       
   542       self:onDecodeError("JSON package groks only UTF-8, sorry", text, nil, etc)
       
   543    end
       
   544 
       
   545    local success, value = pcall(grok_one, self, text, 1, etc)
       
   546    if success then
       
   547       return value
       
   548    else
       
   549       -- should never get here... JSON parse errors should have been caught earlier
       
   550       assert(false, value)
       
   551       return nil
       
   552    end
       
   553 end
       
   554 
       
   555 local function backslash_replacement_function(c)
       
   556    if c == "\n" then
       
   557       return "\\n"
       
   558    elseif c == "\r" then
       
   559       return "\\r"
       
   560    elseif c == "\t" then
       
   561       return "\\t"
       
   562    elseif c == "\b" then
       
   563       return "\\b"
       
   564    elseif c == "\f" then
       
   565       return "\\f"
       
   566    elseif c == '"' then
       
   567       return '\\"'
       
   568    elseif c == '\\' then
       
   569       return '\\\\'
       
   570    else
       
   571       return string.format("\\u%04x", c:byte())
       
   572    end
       
   573 end
       
   574 
       
   575 local chars_to_be_escaped_in_JSON_string
       
   576    = '['
       
   577    ..    '"'    -- class sub-pattern to match a double quote
       
   578    ..    '%\\'  -- class sub-pattern to match a backslash
       
   579    ..    '%z'   -- class sub-pattern to match a null
       
   580    ..    '\001' .. '-' .. '\031' -- class sub-pattern to match control characters
       
   581    .. ']'
       
   582 
       
   583 local function json_string_literal(value)
       
   584    local newval = value:gsub(chars_to_be_escaped_in_JSON_string, backslash_replacement_function)
       
   585    return '"' .. newval .. '"'
       
   586 end
       
   587 
       
   588 local function object_or_array(self, T, etc)
       
   589    --
       
   590    -- We need to inspect all the keys... if there are any strings, we'll convert to a JSON
       
   591    -- object. If there are only numbers, it's a JSON array.
       
   592    --
       
   593    -- If we'll be converting to a JSON object, we'll want to sort the keys so that the
       
   594    -- end result is deterministic.
       
   595    --
       
   596    local string_keys = { }
       
   597    local number_keys = { }
       
   598    local number_keys_must_be_strings = false
       
   599    local maximum_number_key
       
   600 
       
   601    for key in pairs(T) do
       
   602       if type(key) == 'string' then
       
   603          table.insert(string_keys, key)
       
   604       elseif type(key) == 'number' then
       
   605          table.insert(number_keys, key)
       
   606          if key <= 0 or key >= math.huge then
       
   607             number_keys_must_be_strings = true
       
   608          elseif not maximum_number_key or key > maximum_number_key then
       
   609             maximum_number_key = key
       
   610          end
       
   611       else
       
   612          self:onEncodeError("can't encode table with a key of type " .. type(key), etc)
       
   613       end
       
   614    end
       
   615 
       
   616    if #string_keys == 0 and not number_keys_must_be_strings then
       
   617       --
       
   618       -- An empty table, or a numeric-only array
       
   619       --
       
   620       if #number_keys > 0 then
       
   621          return nil, maximum_number_key -- an array
       
   622       elseif tostring(T) == "JSON array" then
       
   623          return nil
       
   624       elseif tostring(T) == "JSON object" then
       
   625          return { }
       
   626       else
       
   627          -- have to guess, so we'll pick array, since empty arrays are likely more common than empty objects
       
   628          return nil
       
   629       end
       
   630    end
       
   631 
       
   632    table.sort(string_keys)
       
   633 
       
   634    local map
       
   635    if #number_keys > 0 then
       
   636       --
       
   637       -- If we're here then we have either mixed string/number keys, or numbers inappropriate for a JSON array
       
   638       -- It's not ideal, but we'll turn the numbers into strings so that we can at least create a JSON object.
       
   639       --
       
   640 
       
   641       if JSON.noKeyConversion then
       
   642          self:onEncodeError("a table with both numeric and string keys could be an object or array; aborting", etc)
       
   643       end
       
   644 
       
   645       --
       
   646       -- Have to make a shallow copy of the source table so we can remap the numeric keys to be strings
       
   647       --
       
   648       map = { }
       
   649       for key, val in pairs(T) do
       
   650          map[key] = val
       
   651       end
       
   652 
       
   653       table.sort(number_keys)
       
   654 
       
   655       --
       
   656       -- Throw numeric keys in there as strings
       
   657       --
       
   658       for _, number_key in ipairs(number_keys) do
       
   659          local string_key = tostring(number_key)
       
   660          if map[string_key] == nil then
       
   661             table.insert(string_keys , string_key)
       
   662             map[string_key] = T[number_key]
       
   663          else
       
   664             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)
       
   665          end
       
   666       end
       
   667    end
       
   668 
       
   669    return string_keys, nil, map
       
   670 end
       
   671 
       
   672 --
       
   673 -- Encode
       
   674 --
       
   675 local encode_value -- must predeclare because it calls itself
       
   676 function encode_value(self, value, parents, etc, indent) -- non-nil indent means pretty-printing
       
   677 
       
   678    if value == nil then
       
   679       return 'null'
       
   680 
       
   681    elseif type(value) == 'string' then
       
   682       return json_string_literal(value)
       
   683 
       
   684    elseif type(value) == 'number' then
       
   685       if value ~= value then
       
   686          --
       
   687          -- NaN (Not a Number).
       
   688          -- JSON has no NaN, so we have to fudge the best we can. This should really be a package option.
       
   689          --
       
   690          return "null"
       
   691       elseif value >= math.huge then
       
   692          --
       
   693          -- Positive infinity. JSON has no INF, so we have to fudge the best we can. This should
       
   694          -- really be a package option. Note: at least with some implementations, positive infinity
       
   695          -- is both ">= math.huge" and "<= -math.huge", which makes no sense but that's how it is.
       
   696          -- Negative infinity is properly "<= -math.huge". So, we must be sure to check the ">="
       
   697          -- case first.
       
   698          --
       
   699          return "1e+9999"
       
   700       elseif value <= -math.huge then
       
   701          --
       
   702          -- Negative infinity.
       
   703          -- JSON has no INF, so we have to fudge the best we can. This should really be a package option.
       
   704          --
       
   705          return "-1e+9999"
       
   706       else
       
   707          return tostring(value)
       
   708       end
       
   709 
       
   710    elseif type(value) == 'boolean' then
       
   711       return tostring(value)
       
   712 
       
   713    elseif type(value) ~= 'table' then
       
   714       self:onEncodeError("can't convert " .. type(value) .. " to JSON", etc)
       
   715 
       
   716    else
       
   717       --
       
   718       -- A table to be converted to either a JSON object or array.
       
   719       --
       
   720       local T = value
       
   721 
       
   722       if parents[T] then
       
   723          self:onEncodeError("table " .. tostring(T) .. " is a child of itself", etc)
       
   724       else
       
   725          parents[T] = true
       
   726       end
       
   727 
       
   728       local result_value
       
   729 
       
   730       local object_keys, maximum_number_key, map = object_or_array(self, T, etc)
       
   731       if maximum_number_key then
       
   732          --
       
   733          -- An array...
       
   734          --
       
   735          local ITEMS = { }
       
   736          for i = 1, maximum_number_key do
       
   737             table.insert(ITEMS, encode_value(self, T[i], parents, etc, indent))
       
   738          end
       
   739 
       
   740          if indent then
       
   741             result_value = "[ " .. table.concat(ITEMS, ", ") .. " ]"
       
   742          else
       
   743             result_value = "[" .. table.concat(ITEMS, ",") .. "]"
       
   744          end
       
   745 
       
   746       elseif object_keys then
       
   747          --
       
   748          -- An object
       
   749          --
       
   750          local TT = map or T
       
   751 
       
   752          if indent then
       
   753 
       
   754             local KEYS = { }
       
   755             local max_key_length = 0
       
   756             for _, key in ipairs(object_keys) do
       
   757                local encoded = encode_value(self, tostring(key), parents, etc, "")
       
   758                max_key_length = math.max(max_key_length, #encoded)
       
   759                table.insert(KEYS, encoded)
       
   760             end
       
   761             local key_indent = indent .. "    "
       
   762             local subtable_indent = indent .. string.rep(" ", max_key_length + 2 + 4)
       
   763             local FORMAT = "%s%" .. string.format("%d", max_key_length) .. "s: %s"
       
   764 
       
   765             local COMBINED_PARTS = { }
       
   766             for i, key in ipairs(object_keys) do
       
   767                local encoded_val = encode_value(self, TT[key], parents, etc, subtable_indent)
       
   768                table.insert(COMBINED_PARTS, string.format(FORMAT, key_indent, KEYS[i], encoded_val))
       
   769             end
       
   770             result_value = "{\n" .. table.concat(COMBINED_PARTS, ",\n") .. "\n" .. indent .. "}"
       
   771 
       
   772          else
       
   773 
       
   774             local PARTS = { }
       
   775             for _, key in ipairs(object_keys) do
       
   776                local encoded_val = encode_value(self, TT[key],       parents, etc, indent)
       
   777                local encoded_key = encode_value(self, tostring(key), parents, etc, indent)
       
   778                table.insert(PARTS, string.format("%s:%s", encoded_key, encoded_val))
       
   779             end
       
   780             result_value = "{" .. table.concat(PARTS, ",") .. "}"
       
   781 
       
   782          end
       
   783       else
       
   784          --
       
   785          -- An empty array/object... we'll treat it as an array, though it should really be an option
       
   786          --
       
   787          result_value = "[]"
       
   788       end
       
   789 
       
   790       parents[T] = false
       
   791       return result_value
       
   792    end
       
   793 end
       
   794 
       
   795 
       
   796 function OBJDEF:encode(value, etc)
       
   797    if type(self) ~= 'table' or self.__index ~= OBJDEF then
       
   798       OBJDEF:onEncodeError("JSON:encode must be called in method format", etc)
       
   799    end
       
   800    return encode_value(self, value, {}, etc, nil)
       
   801 end
       
   802 
       
   803 function OBJDEF:encode_pretty(value, etc)
       
   804    if type(self) ~= 'table' or self.__index ~= OBJDEF then
       
   805       OBJDEF:onEncodeError("JSON:encode_pretty must be called in method format", etc)
       
   806    end
       
   807    return encode_value(self, value, {}, etc, "")
       
   808 end
       
   809 
       
   810 function OBJDEF.__tostring()
       
   811    return "JSON encode/decode package"
       
   812 end
       
   813 
       
   814 OBJDEF.__index = OBJDEF
       
   815 
       
   816 function OBJDEF:new(args)
       
   817    local new = { }
       
   818 
       
   819    if args then
       
   820       for key, val in pairs(args) do
       
   821          new[key] = val
       
   822       end
       
   823    end
       
   824 
       
   825    return setmetatable(new, OBJDEF)
       
   826 end
       
   827 
       
   828 return OBJDEF:new()
       
   829 
       
   830 --
       
   831 -- Version history:
       
   832 --
       
   833 --   20131118.9    Update for Lua 5.3... it seems that tostring(2/1) produces "2.0" instead of "2",
       
   834 --                 and this caused some problems.
       
   835 --
       
   836 --   20131031.8    Unified the code for encode() and encode_pretty(); they had been stupidly separate,
       
   837 --                 and had of course diverged (encode_pretty didn't get the fixes that encode got, so
       
   838 --                 sometimes produced incorrect results; thanks to Mattie for the heads up).
       
   839 --
       
   840 --                 Handle encoding tables with non-positive numeric keys (unlikely, but possible).
       
   841 --
       
   842 --                 If a table has both numeric and string keys, or its numeric keys are inappropriate
       
   843 --                 (such as being non-positive or infinite), the numeric keys are turned into
       
   844 --                 string keys appropriate for a JSON object. So, as before,
       
   845 --                         JSON:encode({ "one", "two", "three" })
       
   846 --                 produces the array
       
   847 --                         ["one","two","three"]
       
   848 --                 but now something with mixed key types like
       
   849 --                         JSON:encode({ "one", "two", "three", SOMESTRING = "some string" }))
       
   850 --                 instead of throwing an error produces an object:
       
   851 --                         {"1":"one","2":"two","3":"three","SOMESTRING":"some string"}
       
   852 --
       
   853 --                 To maintain the prior throw-an-error semantics, set
       
   854 --                      JSON.noKeyConversion = true
       
   855 --                 
       
   856 --   20131004.7    Release under a Creative Commons CC-BY license, which I should have done from day one, sorry.
       
   857 --
       
   858 --   20130120.6    Comment update: added a link to the specific page on my blog where this code can
       
   859 --                 be found, so that folks who come across the code outside of my blog can find updates
       
   860 --                 more easily.
       
   861 --
       
   862 --   20111207.5    Added support for the 'etc' arguments, for better error reporting.
       
   863 --
       
   864 --   20110731.4    More feedback from David Kolf on how to make the tests for Nan/Infinity system independent.
       
   865 --
       
   866 --   20110730.3    Incorporated feedback from David Kolf at http://lua-users.org/wiki/JsonModules:
       
   867 --
       
   868 --                   * When encoding lua for JSON, Sparse numeric arrays are now handled by
       
   869 --                     spitting out full arrays, such that
       
   870 --                        JSON:encode({"one", "two", [10] = "ten"})
       
   871 --                     returns
       
   872 --                        ["one","two",null,null,null,null,null,null,null,"ten"]
       
   873 --
       
   874 --                     In 20100810.2 and earlier, only up to the first non-null value would have been retained.
       
   875 --
       
   876 --                   * When encoding lua for JSON, numeric value NaN gets spit out as null, and infinity as "1+e9999".
       
   877 --                     Version 20100810.2 and earlier created invalid JSON in both cases.
       
   878 --
       
   879 --                   * Unicode surrogate pairs are now detected when decoding JSON.
       
   880 --
       
   881 --   20100810.2    added some checking to ensure that an invalid Unicode character couldn't leak in to the UTF-8 encoding
       
   882 --
       
   883 --   20100731.1    initial public release
       
   884 --