[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: Any plans for providing JSON in Xavante?
- From: Romulo Bahiense <romulo@...>
- Date: Wed, 03 Aug 2005 10:10:21 -0300
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.