SHARE
TWEET

json

ElvishJerricco Nov 9th, 2012 (edited) 25,009 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. ------------------------------------------------------------------ utils
  2. local controls = {["\n"]="\\n", ["\r"]="\\r", ["\t"]="\\t", ["\b"]="\\b", ["\f"]="\\f", ["\""]="\\\"", ["\\"]="\\\\"}
  3.  
  4. local function isArray(t)
  5.     local max = 0
  6.     for k,v in pairs(t) do
  7.         if type(k) ~= "number" then
  8.             return false
  9.         elseif k > max then
  10.             max = k
  11.         end
  12.     end
  13.     return max == #t
  14. end
  15.  
  16. local whites = {['\n']=true; ['\r']=true; ['\t']=true; [' ']=true; [',']=true; [':']=true}
  17. function removeWhite(str)
  18.     while whites[str:sub(1, 1)] do
  19.         str = str:sub(2)
  20.     end
  21.     return str
  22. end
  23.  
  24. ------------------------------------------------------------------ encoding
  25.  
  26. local function encodeCommon(val, pretty, tabLevel, tTracking)
  27.     local str = ""
  28.  
  29.     -- Tabbing util
  30.     local function tab(s)
  31.         str = str .. ("\t"):rep(tabLevel) .. s
  32.     end
  33.  
  34.     local function arrEncoding(val, bracket, closeBracket, iterator, loopFunc)
  35.         str = str .. bracket
  36.         if pretty then
  37.             str = str .. "\n"
  38.             tabLevel = tabLevel + 1
  39.         end
  40.         for k,v in iterator(val) do
  41.             tab("")
  42.             loopFunc(k,v)
  43.             str = str .. ","
  44.             if pretty then str = str .. "\n" end
  45.         end
  46.         if pretty then
  47.             tabLevel = tabLevel - 1
  48.         end
  49.         if str:sub(-2) == ",\n" then
  50.             str = str:sub(1, -3) .. "\n"
  51.         elseif str:sub(-1) == "," then
  52.             str = str:sub(1, -2)
  53.         end
  54.         tab(closeBracket)
  55.     end
  56.  
  57.     -- Table encoding
  58.     if type(val) == "table" then
  59.         assert(not tTracking[val], "Cannot encode a table holding itself recursively")
  60.         tTracking[val] = true
  61.         if isArray(val) then
  62.             arrEncoding(val, "[", "]", ipairs, function(k,v)
  63.                 str = str .. encodeCommon(v, pretty, tabLevel, tTracking)
  64.             end)
  65.         else
  66.             arrEncoding(val, "{", "}", pairs, function(k,v)
  67.                 assert(type(k) == "string", "JSON object keys must be strings", 2)
  68.                 str = str .. encodeCommon(k, pretty, tabLevel, tTracking)
  69.                 str = str .. (pretty and ": " or ":") .. encodeCommon(v, pretty, tabLevel, tTracking)
  70.             end)
  71.         end
  72.     -- String encoding
  73.     elseif type(val) == "string" then
  74.         str = '"' .. val:gsub("[%c\"\\]", controls) .. '"'
  75.     -- Number encoding
  76.     elseif type(val) == "number" or type(val) == "boolean" then
  77.         str = tostring(val)
  78.     else
  79.         error("JSON only supports arrays, objects, numbers, booleans, and strings", 2)
  80.     end
  81.     return str
  82. end
  83.  
  84. function encode(val)
  85.     return encodeCommon(val, false, 0, {})
  86. end
  87.  
  88. function encodePretty(val)
  89.     return encodeCommon(val, true, 0, {})
  90. end
  91.  
  92. ------------------------------------------------------------------ decoding
  93.  
  94. local decodeControls = {}
  95. for k,v in pairs(controls) do
  96.     decodeControls[v] = k
  97. end
  98.  
  99. function parseBoolean(str)
  100.     if str:sub(1, 4) == "true" then
  101.         return true, removeWhite(str:sub(5))
  102.     else
  103.         return false, removeWhite(str:sub(6))
  104.     end
  105. end
  106.  
  107. function parseNull(str)
  108.     return nil, removeWhite(str:sub(5))
  109. end
  110.  
  111. local numChars = {['e']=true; ['E']=true; ['+']=true; ['-']=true; ['.']=true}
  112. function parseNumber(str)
  113.     local i = 1
  114.     while numChars[str:sub(i, i)] or tonumber(str:sub(i, i)) do
  115.         i = i + 1
  116.     end
  117.     local val = tonumber(str:sub(1, i - 1))
  118.     str = removeWhite(str:sub(i))
  119.     return val, str
  120. end
  121.  
  122. function parseString(str)
  123.     str = str:sub(2)
  124.     local s = ""
  125.     while str:sub(1,1) ~= "\"" do
  126.         local next = str:sub(1,1)
  127.         str = str:sub(2)
  128.         assert(next ~= "\n", "Unclosed string")
  129.  
  130.         if next == "\\" then
  131.             local escape = str:sub(1,1)
  132.             str = str:sub(2)
  133.  
  134.             next = assert(decodeControls[next..escape], "Invalid escape character")
  135.         end
  136.  
  137.         s = s .. next
  138.     end
  139.     return s, removeWhite(str:sub(2))
  140. end
  141.  
  142. function parseArray(str)
  143.     str = removeWhite(str:sub(2))
  144.  
  145.     local val = {}
  146.     local i = 1
  147.     while str:sub(1, 1) ~= "]" do
  148.         local v = nil
  149.         v, str = parseValue(str)
  150.         val[i] = v
  151.         i = i + 1
  152.         str = removeWhite(str)
  153.     end
  154.     str = removeWhite(str:sub(2))
  155.     return val, str
  156. end
  157.  
  158. function parseObject(str)
  159.     str = removeWhite(str:sub(2))
  160.  
  161.     local val = {}
  162.     while str:sub(1, 1) ~= "}" do
  163.         local k, v = nil, nil
  164.         k, v, str = parseMember(str)
  165.         val[k] = v
  166.         str = removeWhite(str)
  167.     end
  168.     str = removeWhite(str:sub(2))
  169.     return val, str
  170. end
  171.  
  172. function parseMember(str)
  173.     local k = nil
  174.     k, str = parseValue(str)
  175.     local val = nil
  176.     val, str = parseValue(str)
  177.     return k, val, str
  178. end
  179.  
  180. function parseValue(str)
  181.     local fchar = str:sub(1, 1)
  182.     if fchar == "{" then
  183.         return parseObject(str)
  184.     elseif fchar == "[" then
  185.         return parseArray(str)
  186.     elseif tonumber(fchar) ~= nil or numChars[fchar] then
  187.         return parseNumber(str)
  188.     elseif str:sub(1, 4) == "true" or str:sub(1, 5) == "false" then
  189.         return parseBoolean(str)
  190.     elseif fchar == "\"" then
  191.         return parseString(str)
  192.     elseif str:sub(1, 4) == "null" then
  193.         return parseNull(str)
  194.     end
  195.     return nil
  196. end
  197.  
  198. function decode(str)
  199.     str = removeWhite(str)
  200.     t = parseValue(str)
  201.     return t
  202. end
  203.  
  204. function decodeFromFile(path)
  205.     local file = assert(fs.open(path, "r"))
  206.     local decoded = decode(file.readAll())
  207.     file.close()
  208.     return decoded
  209. end
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
Not a member of Pastebin yet?
Sign Up, it unlocks many cool features!
 
Top