Advertisement
FFGFlash

api/json.lua

Sep 30th, 2021 (edited)
53
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 3.31 KB | None | 0 0
  1. -- Implementation of ElvishJerricco's JSON api
  2. local api = { LoadOrder = 100 }
  3. function api.Build()
  4.   local whites={["\n"]=true,["\r"]=true,["\t"]=true,[" "]=true,[","]=true,[":"]=true}
  5.   local numChars={["e"]=true,["E"]=true,["+"]=true,["-"]=true,["."]=true}
  6.   local escaped={["\n"]="\\n",["\r"]="\\r",["\t"]="\\t",["\b"]="\\b",["\f"]="\\f",["\""]="\\\"",["\\"]="\\\\"}
  7.   local iescaped={}
  8.   for k,v in pairs(escaped) do iescaped[v]=k end
  9.   function removeWhite(s) while whites[s:sub(1,1)] do s=s:sub(2) end return s end
  10.   function parseBoolean(s) local v=s:sub(1,4)=="true" return v,removeWhite(s:sub(v and 5 or 6)) end
  11.   function parseNull(s) return nil,removeWhite(s:sub(5)) end
  12.   function parseNumber(s) local i=1 while numChars[s:sub(i,i)] or tonumber(s:sub(i,i)) do i=i+1 end local v=tonumber(s:sub(1,i-1)) s=removeWhite(s:sub(i)) return v,s end
  13.   function parseString(s) s=s:sub(2) local v="" while s:sub(1,1)~="\"" do local n=s:sub(1,1) s=s:sub(2) assert(n~="\n","Unclosed string") if n=="\\" then local e=s:sub(1,1) s=s:sub(2) n=assert(iescaped[n..e],"Invalid escape character") end v=v..n end return v,removeWhite(s:sub(2)) end
  14.   function parseArray(s) s=removeWhite(s:sub(2)) local a,i={},1 while s:sub(1,1)~="]" do local v = nil v,s=parseValue(s) a[i]=v i=i+1 s=removeWhite(s) end s=removeWhite(s:sub(2)) return a,s end
  15.   function parseObject(s) s=removeWhite(s:sub(2)) local t={} while s:sub(1,1)~="}" do local k,v=nil,nil k,v,s=parseMember(s) t[k]=v s=removeWhite(s) end s=removeWhite(s:sub(2)) return t,s end
  16.   function parseMember(s) local k,v=nil,nil k,s=parseValue(s) v,s=parseValue(s) return k,v,s end
  17.   function parseValue(s) local f=s:sub(1,1) if f=="{" then return parseObject(s) elseif f=="[" then return parseArray(s) elseif tonumber(f)~=nil or numChars[f] then return parseNumber(s) elseif s:sub(1,4)=="true" or s:sub(1,5)=="false" then return parseBoolean(s) elseif f=="\"" then return parseString(s) elseif s:sub(1,4)=="null" then return parseNull(s) end return nil end
  18.   local json = {}
  19.   function json:parse(s) return parseValue(removeWhite(s)) end
  20.   function json:stringify(t,p,u,o)
  21.     local s = ""
  22.     p,u,o=p or false,u or 0,o or {}
  23.     local function tab(i) s=s..("\t"):rep(u)..i end
  24.     local function encoding(t,b,c,i,l)
  25.       s=s..b
  26.       if p then s=s.."\n" u=u+1 end
  27.       for k,v in i(t) do
  28.         tab("")
  29.         l(k,v)
  30.         s=s..","
  31.         if p then s=s.."\n" end
  32.       end
  33.       if p then u=u-1 end
  34.       if s:sub(-2)==",\n" then s=s:sub(1,-3).."\n"
  35.       elseif s:sub(-1)=="," then s=s:sub(1,-2) end
  36.       tab(c)
  37.     end
  38.     if type(t)=="table" then
  39.       assert(not o[t],"Cannot handle cyclic tables")
  40.       o[t]=true
  41.       if table.isArray(t) then
  42.         encoding(t,"[","]",ipairs,function(k,v)
  43.           s=s..self:stringify(v,p,u,o)
  44.         end)
  45.       else
  46.         encoding(t,"{","}",pairs,function(k,v)
  47.           assert(type(k)=="string","JSON Object keys must be strings",2)
  48.           s=s..self:stringify(k,p,u,o)
  49.           s=s..(p and ": " or ":")..self:stringify(v,p,u,o)
  50.         end)
  51.       end
  52.     elseif type(t)=="string" then s="\""..t:gsub("[%c\"\\]",escaped).."\""
  53.     elseif type(t)=="number" or type(t)=="boolean" then s=tostring(t)
  54.     else error("JSON only supports arrays, objects, numbers, booleans and strings",2) end
  55.     return s
  56.   end
  57.   return json
  58. end
  59. return api
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement