先分词,再解析,少写了语法检查
module( "json_to_lua", package.seeall )--##############################################################################--# 模块接口--##############################################################################-- json字符串转lua tablefunction JsonStrToLuaTable( szJsonStr ) local tWords = SplitWord( szJsonStr ) -- 此处应该加一个语法检查的 -- CheckSyntax( tWords ) local ResultObj = CreateObjectByWords( tWords ) return ResultObjend-- lua table转jsonfunction LuaTableToJsonStr( tTable, nTabCnt ) nTabCnt = nTabCnt or 0 local szJsonStr = "" assert( type( tTable ) == "table", "tTable is not a table." ) local szTab = "" for i = 1, nTabCnt do szTab = szTab .. '' end local szKeyType = nil for key, value in pairs( tTable ) do if szKeyType == nil then szKeyType = type( key ) if szKeyType ~= "string" and szKeyType ~= "number" then -- 处理不了其他类型的key return nil end end -- 处理key,key类型不一致,转换失败 if type( key ) ~= szKeyType then return nil end szJsonStr = szJsonStr .. '' .. szTab if szKeyType == "string" then szJsonStr = szJsonStr .. string.format( ""%s" = ", EscDecode( key ) ) end -- 处理value if type( value ) == "table" then szJsonStr = szJsonStr .. LuaTableToJsonStr( value, nTabCnt + 1 ) .. "," else if type( value ) == 'string' then value = '"' .. EscDecode( value ) .. '"' end szJsonStr = szJsonStr .. string.format( "%s,", value ) end end if szJsonStr == '' then szTab = ''; szJsonStr = '' end if szKeyType == "string" then return "{" .. szJsonStr .. szTab .. '}' else return "[" .. szJsonStr .. szTab .. ']' endend-- 文件中读json文件并转成Lua tablefunction JsonFileToLuaTable( szJsonFileName ) local JsonFileObj = io.open( szJsonFileName, 'r' ) if JsonFileObj == nil then return nil end local szJsonStr = JsonFileObj:read( "*a" ) io.close( JsonFileObj ) return JsonStrToLuaTable( szJsonStr )end-- Lua table生成json并保存到文件function LuaTableToJsonFile( tTable, szJsonFileName ) local JsonFileObj = io.open( szJsonFileName, 'w' ) szJsonStr = LuaTableToJsonStr( tTable ) if szJsonStr == nil then return false else JsonFileObj:write(szJsonStr) io.close( JsonFileObj ) return true endend--##############################################################################--# 主要函数--##############################################################################tJson2Lua = { ["true"] = { value = true }, ["null"] = { value = nil }, ["false"] = { value = false },}tStr2Esc = { ["""] = '"', ["f"] = 'f', [""] = '', ["/"] = '/', ["\"] = '', [""] = '', [""] = '', [""] = '',}tEsc2Str = { ['"'] = """, ['f'] = "f", [''] = "", ['/'] = "/", [''] = "", [''] = "", [''] = ""}-- 分词function SplitWord( szJsonStr ) local tWords = {} if szJsonStr == nil then return nil end szJsonStr = StringTrim( szJsonStr ) local nIndex = 1 while nIndex <= #szJsonStr do repeat -- breake实现continue local szChar = szJsonStr:sub( nIndex, nIndex ) -- 跳过空白字符 if ( " " ):find( szChar, 1, true ) then break end -- 处理语法的字符和字符串 if ( "{:}[,]"" ):find( szChar, 1, true ) then tWords[#tWords + 1] = szChar if szChar == '"' then local szTempStr = "" nIndex = nIndex + 1 local szNextChar = szJsonStr:sub( nIndex, nIndex ) while szNextChar ~= szChar do szTempStr = szTempStr .. szNextChar if szNextChar == '' and nIndex + 1 <= #szJsonStr then nIndex = nIndex + 1 szTempStr = szTempStr .. szJsonStr:sub( nIndex, nIndex ) end nIndex = nIndex + 1 szNextChar = szJsonStr:sub( nIndex, nIndex ) end tWords[#tWords + 1] = szTempStr tWords[#tWords + 1] = szChar end -- 处理数字 elseif CharIsDigit(szChar) or szChar == '-' or szChar == '.' then local szNumStr = szChar if szChar == '.' then szNumStr = '0.' end while nIndex + 1 <= #szJsonStr do local szNextChar = szJsonStr:sub( nIndex + 1, nIndex + 1 ) if ( "AaBbCcDdEeFfXx. -+" ):find( szNextChar, 1, true ) or CharIsDigit( szNextChar ) then if szNextChar ~= ' ' then szNumStr = szNumStr .. szNextChar end nIndex = nIndex + 1 else break end end tWords[#tWords + 1] = szNumStr elseif CharIsAlpha( szChar ) then local szTempStr = szChar while nIndex + 1 <= #szJsonStr do local szNextChar = szJsonStr:sub( nIndex + 1, nIndex + 1 ) if CharIsAlpha( szNextChar ) then szTempStr = szTempStr .. szNextChar nIndex = nIndex + 1 else break end end tWords[#tWords + 1] = szTempStr end until ( true ) -- breake实现continue nIndex = nIndex + 1 end return tWordsend-- 根据分词创建对象function CreateObjectByWords( tWords, tCur ) tCur = tCur or { 1 } local nIndex = tCur[1] -- 处理字典 if tWords[nIndex] == '{' then local ResultObj = {} nIndex = nIndex + 1 while nIndex <= #tWords do if tWords[nIndex] == '}' then tCur[1] = nIndex return ResultObj elseif tWords[nIndex] == '"' then szKey = EscEncode( tWords[nIndex + 1] ) tCur[1] = nIndex + 4 ResultObj[szKey] = CreateObjectByWords( tWords, tCur ) nIndex = tCur[1] end nIndex = nIndex + 1 end -- 处理数组 elseif tWords[nIndex] == '[' then local ResultObj = {} local nArrayLen = 0 nIndex = nIndex + 1 while nIndex <= #tWords do if tWords[nIndex] == ']' then tCur[1] = nIndex return ResultObj elseif tWords[nIndex] ~= ',' then tCur[1] = nIndex ResultObj[nArrayLen + 1] = CreateObjectByWords( tWords, tCur ) nArrayLen = nArrayLen + 1 nIndex = tCur[1] end nIndex = nIndex + 1 end -- 处理字符串 elseif tWords[nIndex] == '"' then tCur[1] = nIndex + 2 return EscEncode( tWords[nIndex + 1] ) -- 处理false, true, null elseif tJson2Lua[tWords[nIndex]] ~= nil then return tJson2Lua[tWords[nIndex]].value elseif tWords[nIndex] ~= ',' then return tonumber( tWords[nIndex] ) endend-- 处理转义字符function EscEncode( szString ) for str, esc in pairs( tStr2Esc ) do szString = string.gsub( szString, str, esc) end return szStringendfunction EscDecode( szString ) szString = string.gsub( szString, '', "\") for esc, str in pairs( tEsc2Str ) do szString = string.gsub( szString, esc, str) end return szStringend-- 打印lua tablefunction PrintTable( tTable, szContext, nTabCnt ) nTabCnt = nTabCnt or 0 szContext = szContext or "" assert( type( tTable ) == "table", "tTable is not a table." ) local szTab = "" for i = 1, nTabCnt do szTab = szTab .. '' end print( szContext .. '{' ) for key, value in pairs( tTable ) do if type( key ) == 'string' then key = '"' .. EscDecode( key ) .. '"' end local szTemp = '' .. szTab .. string.format( "[%s] = ", key ) if type( value ) == "table" then PrintTable( value, szTemp, nTabCnt + 1) else if type( value ) == 'string' then value = '"' .. EscDecode( value ) .. '"' end print( szTemp .. string.format( "%s,", value ) ) end end print( szTab .. '}' )end--##############################################################################--# 字符串辅助函数--##############################################################################-- 删除前后空白字符function StringTrim( szString ) if type( szString ) ~= "string" then return "" end return ( string.gsub( string.gsub( szString, "%s+$", "" ), "^%s+", "" ) )end-- 判断是数字function CharIsDigit( szChar ) assert( #szChar == 1, "szChar is not a char: " .. szChar ) return ( '0' ):byte() <= szChar:byte() and szChar:byte() <= ( '9' ):byte()end-- 判断是字母function CharIsAlpha( szChar ) assert( #szChar == 1, "szChar is not a char: " .. szChar ) return ( ( 'a' ):byte() <= szChar:byte() and szChar:byte() <= ( 'z' ):byte() ) or ( ( 'A' ):byte() <= szChar:byte() and szChar:byte() <= ( 'Z' ):byte() )end
测试用例:
{ "root": [ "JSON Test Pattern pass1", { "object with 1 member": [ "array with 1 element" ] }, {}, [], -42, true, false, null, { "integer": 1234567890, "real": -9876.54321, "e": 1.23456789e-13, "E": 1.23456789e+34, "zero": 0, "one": 1, "space": " ", "quote": """, "backslash": "", "slash": "/ & /", "alpha": "abcdefghijklmnopqrstuvwyz", "ALPHA": "ABCDEFGHIJKLMNOPQRSTUVWYZ", "digit": "0123456789" }, 0.5, 98.6, 99.44, 1066, "rosebud" ] }