Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- -- Implementation of ElvishJerricco's JSON api
- local api = { LoadOrder = 100 }
- function api.Build()
- local whites={["\n"]=true,["\r"]=true,["\t"]=true,[" "]=true,[","]=true,[":"]=true}
- local numChars={["e"]=true,["E"]=true,["+"]=true,["-"]=true,["."]=true}
- local escaped={["\n"]="\\n",["\r"]="\\r",["\t"]="\\t",["\b"]="\\b",["\f"]="\\f",["\""]="\\\"",["\\"]="\\\\"}
- local iescaped={}
- for k,v in pairs(escaped) do iescaped[v]=k end
- function removeWhite(s) while whites[s:sub(1,1)] do s=s:sub(2) end return s end
- function parseBoolean(s) local v=s:sub(1,4)=="true" return v,removeWhite(s:sub(v and 5 or 6)) end
- function parseNull(s) return nil,removeWhite(s:sub(5)) end
- 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
- 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
- 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
- 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
- function parseMember(s) local k,v=nil,nil k,s=parseValue(s) v,s=parseValue(s) return k,v,s end
- 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
- local json = {}
- function json:parse(s) return parseValue(removeWhite(s)) end
- function json:stringify(t,p,u,o)
- local s = ""
- p,u,o=p or false,u or 0,o or {}
- local function tab(i) s=s..("\t"):rep(u)..i end
- local function encoding(t,b,c,i,l)
- s=s..b
- if p then s=s.."\n" u=u+1 end
- for k,v in i(t) do
- tab("")
- l(k,v)
- s=s..","
- if p then s=s.."\n" end
- end
- if p then u=u-1 end
- if s:sub(-2)==",\n" then s=s:sub(1,-3).."\n"
- elseif s:sub(-1)=="," then s=s:sub(1,-2) end
- tab(c)
- end
- if type(t)=="table" then
- assert(not o[t],"Cannot handle cyclic tables")
- o[t]=true
- if table.isArray(t) then
- encoding(t,"[","]",ipairs,function(k,v)
- s=s..self:stringify(v,p,u,o)
- end)
- else
- encoding(t,"{","}",pairs,function(k,v)
- assert(type(k)=="string","JSON Object keys must be strings",2)
- s=s..self:stringify(k,p,u,o)
- s=s..(p and ": " or ":")..self:stringify(v,p,u,o)
- end)
- end
- elseif type(t)=="string" then s="\""..t:gsub("[%c\"\\]",escaped).."\""
- elseif type(t)=="number" or type(t)=="boolean" then s=tostring(t)
- else error("JSON only supports arrays, objects, numbers, booleans and strings",2) end
- return s
- end
- return json
- end
- return api
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement