lua-users home
lua-l archive

Re: Any plans for providing JSON in Xavante?

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


Hi,
	I couldn't hold it ;)
Please note that the 'decodeJSON' is not very optimal. I had to use some 'string.gsub' to translate from JSON(JS) to Lua, but it actually works :) The only drawback I found so far, was with holes (nil's) inside arrays/lists. PS: No, I don't use and have never used JSON nor CGILua (but I do use a patched Xavante).
--- BEGIN OF CODE ---
-- This code uses the same license as Lua 5
local gsub,sub,find,format = string.gsub,string.sub,string.find,string.format
local replacechars = {["["] = '{'; ["]"] = '}'; [":"] = '='}
function decodeJSON(buffer)
 assert(type(buffer)=='string')
 local strings,stringi = {},1
 -- remove quoted text
 buffer = gsub(buffer, '(".-[^\\]?")',
 function(str)
 if strings[str] then return strings[str] end
 local i = stringi
 stringi = stringi+1
 strings[str] = '%'..i
 strings[i] = str
 return '%'..i
 end)
 -- remove long comments
 buffer = gsub(buffer, '%/%*(.-)%*%/' , '')
 -- remove line comments
 buffer = gsub(buffer, '//(.-)\n' , '')
 -- replace the characters that are different between JS and Lua
buffer = gsub(buffer, '[%[%]%:]' , function(c) return replacechars[c] end)
 -- remove spaces (Have no use, but I like tight things ;))
 -- buffer = gsub(buffer, '%s+' , '')
 -- reinsert quotes
 buffer = gsub(buffer, '%%(%d+)()' ,
 function(i,stop)
 local s = strings[tonumber(i)]
 -- check if the string is used as a key or as value
 if find(buffer, '^%s*%=', stop) then return '['..s..']'
 else return s
 end
 end)
 -- "local null" just avoids global lookup.
 local f, err = loadstring('local null; return ' .. buffer)
 if not f then
 return nil,err
 else
 -- Avoid a bit some attacks
 setfenv(f,{})
 return f()
 end
end
local function encodevalue(value)
 local tv = type(value)
 if tv=='string' then return format('%q',value)
 elseif tv=='number' then return tostring(value)
 elseif tv=='table' then return encodeJSON(value)
 elseif tv=='boolean' then return value and 'true' or 'false'
 elseif tv=='nil' then return 'null'
 else error('Invalid value to encode: '..value)
 end
end
function encodeJSON(value)
 assert(type(value)=='table')
 local s = ''
 local obj = false
 for key in pairs(value) do
 local tk = type(key)
-- Uncomment this line if you only want string keys for Object (I don't
 -- really know if JSON allow anything else than string...)
-- assert(tk=='number' or tk=='string', 'Invalid table key for encoding')
 if tk~='number' then
 obj=true
 break
 end
 end
 if obj then
 local first=true
 for key,val in pairs(value) do
s=(first and '{' or s..',')..format('%q:%s',key,encodevalue(val))
 first=false
 end
 s=s..'}'
 else
 local first=true
 for i,val in ipairs(value) do
 s=(first and '[' or s..',')..encodevalue(val)
 first=false
 end
 s=s..']'
 end
 return s
end
--- END OF CODE ---
Hope it helps,
	Me.

AltStyle によって変換されたページ (->オリジナル) /