--[[
file name : table序列化和反序列化的问题.lua
author : Clark/陈泽丹
created : 2011-12-22
备注:
支持table的递归结构,但数据类型不支持function属性(因为function只是记录地址,在不同机器上序列化和反序列化后的地址相同没什么意义)
后记:
郁闷, 写完到网上一搜, 才发现原来Lua有提供一些现成的函数可用来做序列化和反序列化操作。。。
其中loadstring可以执行字符串。
通过
lua = "return " .. lua
local func = loadstring(lua)
即实现了反序列化。。。
--]]
----------- 个人编写 -----------------
--table转字符串(只取标准写法,以防止因系统的遍历次序导致ID乱序)
function sz_T2S(_t)
local szRet = "{"
function doT2S(_i, _v)
if "number" == type(_i) then
szRet = szRet .. "[" .. _i .. "] = "
if "number" == type(_v) then
szRet = szRet .. _v .. ","
elseif "string" == type(_v) then
szRet = szRet .. '"' .. _v .. '"' .. ","
elseif "table" == type(_v) then
szRet = szRet .. sz_T2S(_v) .. ","
else
szRet = szRet .. "nil,"
end
elseif "string" == type(_i) then
szRet = szRet .. '["' .. _i .. '"] = '
if "number" == type(_v) then
szRet = szRet .. _v .. ","
elseif "string" == type(_v) then
szRet = szRet .. '"' .. _v .. '"' .. ","
elseif "table" == type(_v) then
szRet = szRet .. sz_T2S(_v) .. ","
else
szRet = szRet .. "nil,"
end
end
end
table.foreach(_t, doT2S)
szRet = szRet .. "}"
return szRet
end
--字符串转table(反序列化,异常数据直接返回nil)
function t_S2T(_szText)
--栈
function stack_newStack()
local first = 1
local last = 0
local stack = {}
local m_public = {}
function m_public.pushBack(_tempObj)
last = last + 1
stack[last] = _tempObj
end
function m_public.temp_getBack()
if m_public.bool_isEmpty() then
return nil
else
local val = stack[last]
return val
end
end
function m_public.popBack()
stack[last] = nil
last = last - 1
end
function m_public.bool_isEmpty()
if first > last then
first = 1
last = 0
return true
else
return false
end
end
function m_public.clear()
while false == m_public.bool_isEmpty() do
stack.popFront()
end
end
return m_public
end
function getVal(_szVal)
local s, e = string.find(_szVal,'"',1,string.len(_szVal))
if nil ~= s and nil ~= e then
--return _szVal
return string.sub(_szVal,2,string.len(_szVal)-1)
else
return tonumber(_szVal)
end
end
local m_szText = _szText
local charTemp = string.sub(m_szText,1,1)
if "{" == charTemp then
m_szText = string.sub(m_szText,2,string.len(m_szText))
end
function doS2T()
local tRet = {}
local tTemp = nil
local stackOperator = stack_newStack()
local stackItem = stack_newStack()
local val = ""
while true do
local dLen = string.len(m_szText)
if dLen <= 0 then
break
end
charTemp = string.sub(m_szText,1,1)
if "[" == charTemp or "=" == charTemp then
stackOperator.pushBack(charTemp)
m_szText = string.sub(m_szText,2,dLen)
elseif '"' == charTemp then
local s, e = string.find(m_szText, '"', 2, dLen)
if nil ~= s and nil ~= e then
val = val .. string.sub(m_szText,1,s)
m_szText = string.sub(m_szText,s+1,dLen)
else
return nil
end
elseif "]" == charTemp then
if "[" == stackOperator.temp_getBack() then
stackOperator.popBack()
stackItem.pushBack(val)
val = ""
m_szText = string.sub(m_szText,2,dLen)
else
return nil
end
elseif "," == charTemp then
if "=" == stackOperator.temp_getBack() then
stackOperator.popBack()
local Item = stackItem.temp_getBack()
Item = getVal(Item)
stackItem.popBack()
if nil ~= tTemp then
tRet[Item] = tTemp
tTemp = nil
else
tRet[Item] = getVal(val)
end
val = ""
m_szText = string.sub(m_szText,2,dLen)
else
return nil
end
elseif "{" == charTemp then
m_szText = string.sub(m_szText,2,string.len(m_szText))
local t = doS2T()
if nil ~= t then
szText = sz_T2S(t)
tTemp = t
--val = val .. szText
else
return nil
end
elseif "}" == charTemp then
m_szText = string.sub(m_szText,2,string.len(m_szText))
return tRet
elseif " " ~= charTemp then
val = val .. charTemp
m_szText = string.sub(m_szText,2,dLen)
else
m_szText = string.sub(m_szText,2,dLen)
end
end
return tRet
end
local t = doS2T()
return t
end
--[[
t = {1,2,3,"sdf", a = "df", qe = 3, {7}, qq = {{2,3,a={}}}, }
t.f = {1,2,3}
t.m = {3,4,5}
szT = sz_T2S(t)
print(szT)
print("-----------")
tq = t_S2T(szT)
szT = sz_T2S(tq)
print(szT)
--]]
-------- 网上资料 -------------------
function serialize(obj)
local lua = ""
local t = type(obj)
if t == "number" then
lua = lua .. obj
elseif t == "boolean" then
lua = lua .. tostring(obj)
elseif t == "string" then
lua = lua .. string.format("%q", obj)
elseif t == "table" then
lua = lua .. "{\n"
for k, v in pairs(obj) do
lua = lua .. "[" .. serialize(k) .. "]=" .. serialize(v) .. ",\n"
end
local metatable = getmetatable(obj)
if metatable ~= nil and type(metatable.__index) == "table" then
for k, v in pairs(metatable.__index) do
lua = lua .. "[" .. serialize(k) .. "]=" .. serialize(v) .. ",\n"
end
end
lua = lua .. "}"
elseif t == "nil" then
return nil
else
error("can not serialize a " .. t .. " type.")
end
return lua
end
function unserialize(lua)
local t = type(lua)
if t == "nil" or lua == "" then
return nil
elseif t == "number" or t == "string" or t == "boolean" then
lua = tostring(lua)
else
error("can not unserialize a " .. t .. " type.")
end
lua = "return " .. lua
local func = loadstring(lua)
if func == nil then
return nil
end
return func()
end
data = {["a"] = "a", ["b"] = "b", [1] = 1, [2] = 2, ["t"] = {1, 2, 3}}
local sz = serialize(data)
print(sz)
print("---------")
print(serialize(unserialize(sz)))