lua 序列化[de]serialize 支持 循环(cycle reference)、嵌套(nest) 引用

早已实现,想到个好的方式。兼顾可读性折叠

流程:

  1. 分析出单例、多引用,编号,仅考虑后者。
  2. 代码执行顺序固定,如:
local o=''
local function p(i)
    o=o..i
end
assert({
    p'1',
    a={
        p'2',
        b={p'3'},
        p'4'
    },
} and o=='1234')
View Code
  1. 在首次使用处插入定义,如 R(i,{..}) ,在后续引用处仅仅使用 R[i] 即可。
  2. 对测试例 t={} t[t]=t t.T=t 生成的代码如:
local R=setmetatable({},{
    __index=function(R,id) R[id]={} return R[id] end,
    __call=function(R,id,t)
        if rawget(R,id) then
            for k,v in pairs(t) do--copy
                R[id][k]=v
            end
            t=R[id]
        end
        R[id]=t
        return t
    end,
})
return R(1,{[R[1]]=R[1],["T"]=R[1],})
View Code

脚本(100行,含缩进、键、数组优化、测试,未支持函数)

--by RobertL https://www.cnblogs.com/RobertL/p/14258259.html
local T,P,I,F,SF,C,RP=type,pairs,table.insert,math.floor,string.format,table.concat,string.rep
function D(d)--data to string
    local ts={--[[tables
        [t]=true/false,--has reference
        [id]=true/flase,--could refer (or define at first time)
    ]]}
    local t
    local function S(i)--scan(input)
        t=T(i)
        if t=='table' or (t=='string' and i:len()>10) then
            if not ts[i] then
                ts[i]=ts[i]==false
            else return end
            if t=='table' then for k,v in P(i) do
                S(k);S(v)
            end end
        end
    end
    S(d)
    
    --generate id, clean single instance
    local id=1
    for t,r in pairs(ts) do
        if r then
            ts[t],id=id,id+1
        else
            ts[t]=nil
        end
    end

    local o={--output list
    [[--Generated using Data2String2.lua by RobertL
local _=setmetatable({},{
    __index=function(R,id) R[id]={} return R[id] end,
    __call=function(R,id,t)
        if rawget(R,id) then
            for k,v in pairs(t) do--copy
                R[id][k]=v
            end
            t=R[id]
        end
        R[id]=t
        return t
    end,
})
return ]]}
    local function W(t)--write
        if T(t)=='boolean' then
            print'her'
        end
        t=t=='' and '
' or t
        I(o,t)
    end
    local function I(n)--indent(number)
        W(RP('	',n))
    end
    local function R(i,n,c)--reference(input,config,indent number,cofiger)
        t=T(i)
        local id=t~='number' and ts[i]
        if id then
            W'_'
            if ts[id] then
                W'['W(id)W']'
                return
            else
                W'('W(id)W','
                ts[id]=id
            end
        end
        if t=='string' then
            W(SF('%q',i))
        elseif t=='number' then
            if i==F(i) then
                i=F(i)--convert to integer
            end
            W(i)
        elseif t=='boolean' then
            W(i and 'true' or 'false')
        elseif t=='nil' then
            W'nil'
        elseif t=='table' then
            W'{'
            local is={}
            for ix,v in ipairs(i) do
                W''I(n+1)
                R(v,n+1)W','
                is[ix]=true
            end
            for k,v in P(i) do
                if not is[k] then
                    W''I(n+1)
                    if not (T(k)=='string' and SF(k,'^[%a_]%w*$') and (W(k) or true)) then
                        W'['R(k,n+1)W']'
                    end
                    W'='R(v,n+1)W','
                end
            end
            W''I(n)W'}'
        end
        if id then
            W')'
        end
    end
    R(d,0)
    
    return C(o)
end
if not ... then
    local t={}
    t[t]=t
    t.T=t
    local t2=load(D(t))()
    assert(t2[t2]==t2 and t2.T==t2)
    --
    t={}
    t.T={T1=t}
    t2=load(D(t))()
    assert(t2.T.T1==t2)
    --
    t={a=1.0,b='string','long long string','long long string',[{[false]=false,false,}]=false}
    print(D(t))
end
return D
View Code

待,支持外部引用,内部依赖检测。

格式测试:

t={['a key']=1.0,'short string','long long string','long long string',[{[false]=false,false,}]=false}

return {
    "short string",
    _(1,"long long string"--[[2]]),
    _[1],
    [{
        false,
        [false]=false,
    }]=false,
    ["a key"]=1,
}
View Code
原文地址:https://www.cnblogs.com/RobertL/p/14258259.html