JSON for Lua

Starting with version 2.0, the WebMCP framework contains a JSON library for Lua that can also be used independently of WebMCP.

Design goals & features

  • Good performance due to implementation in C
  • Utilize the Lua type system (tables, strings, numbers, booleans) to directly represent JSON values:
    json.export{key1=17, key2={"arrayentry1", "arrayentry2"}, key3=true}
  • Allow explicit conversion from Lua tables to JSON objects/arrays to avoid ambiguity of the empty table:
    json.export{emptyarray = json.array{}, emptyobject = json.object{}}
    (json.array and json.object do not modify their argument but return a new value)
  • Path based reading:
    json.get(json.import('{"a":{"b":3}}'), "a", "b") == 3
    json.get(json.import('{"a":{"b":3}}'), "c", "d") == nil
  • Path based writing:
    local obj = {a = {b = 3}}; json.set(obj, 7, 'c', 'd')
    print(json.export(obj)) -- prints {"a":{"b":3},"c":{"d":7}}
  • Support for JSON null values:
    • Return nil when accessing a JSON null value:
      if json.import('{"key":null}').key then ... -- won't execute
      if json.import('{"key":true}').key then ... -- will execute
      (Note: In Lua anything but nil and false is considered as true.)
    • Allow testing for null values:
      json.type(json.import('{"key":null}'), "key") == "null"
    • Iterate over null values:
      for i, v in ipairs(json.import('[1,2,null,4]')) do print(v) end
      -- prints 1 2 nil 4
    • Support for setting null values:
      json.export{key=json.null} == '{"key":null}' -- in table
      local obj = json.object{}; obj.key = json.null -- in setter
      (When using JSON objects or arrays instead of tables, reading a value after setting it to json.null will also return nil.)
  • Deterministic (i.e. sorted) output of object keys:
    json.export{b=2, a=1, c=3} == '{"a":1,"b":2,"c":3}'
  • Pretty printing with indentation:
    json.export({key1="value1", key2={"a", "b"}}, "  ") -- returns:
    {
      "key1": "value1",
      "key2": [
        "a",
        "b"
      ]
    }
  • Import and export of deeply nested documents:
    json.import('{{{ ... up to 2^30 nested levels ... }}}')
    -- works if enough memory
    json.import('{{{ ... more than 2^30 nested levels ... }}}')
    -- returns nil plus error message
    (Support for 230 nested levels assures that documents up to 231 Byte = 2 GiB can always be processed as long as enough memory is available)
  • Support of Unicode escape sequences:
    • Bytes ≥ 128 (0x80..0xFF) are passed through (binary safe, no sanitizing)
    • Conversion of escaped UTF-16 surrogates to UTF-8:
      json.import('"\\uD83D\\uDE0E"') == "\xf0\x9f\x98\x8e"
      -- U+1F60E: SMILING FACE WITH SUNGLASSES 😎
    • Rejection of illegal UTF-16 surrogates in escape sequences:
      json.import('"\\uD83D"')
      -- returns nil plus error message:
      -- "Illegal UTF-16 surrogate in JSON string escape sequence"
    • When encoding strings, only the following escape sequences are used:
      \u0000 through \u0007,
      \b, \t, \v, \n, \v, \f, \r,
      \u000E through \u001F,
      \u007F

Dependencies

Download

WebMCP's JSON library for Lua is part of WebMCP (directory "libraries/json/" in the source tarball).