博猪开了CSDN也有一段时间了,但是呢,一直没写,只是在学习。
最近发现解码json串时,如果json串本身格式错误会造成程序报错,那当然不能忍,于是断断续续抽着间隙来写写了一个礼拜终于写了一个较为完整的纯lua脚本来判断json串。
因为json用的不是很多,刚开始只是了解到这样的格式: {“a”:“1”,“b”:“2”,“c”:"3"},还有复杂一点的这种:{ "links": [
{ "a": "1", "b": "2" },
{ "c": "3","d": "4"
}]},对于这种,一开始我想的处理方式是先找[..] 然后截取出来,再找{...}然后找逗号",",截取逗号前部分后后部分,利用到string.gsub判断这一小段是不是 "a":"1"这样的格式,源码如下,后面还有处理无限嵌套json的源码:
--判断是否是json
function ifIsJson(jsonString)
local head
local pos1,pos2
jsonString =jsonString:atrim()
local String1=string.sub(jsonString,1,1) --最外部大括号
local String2 = string.sub(jsonString,#jsonString)
if String1=="{" and String2 =="}" then
String1=jsonString
jsonString=string.sub(jsonString,2,-2) --去掉最外部括号
pos1,_=string.find(jsonString,"%[")
if pos1 then
pos2,_ = string.find(jsonString,"%]")
if pos2 then
head=string.sub(jsonString,2,pos1-1)
local a,b=string.gsub(head,"(\"-)(.-)(\"-):","")
if a =="" and b==1 then
head=string.sub(jsonString,pos1+1,pos2-1)
while true do
if (pos2)==#jsonString then --没有后续的了
local result= ContinueCheck(head) --传入 []里的内容
if result then return true else return false end
else --还有
local result= ContinueCheck(head) --传入 []里的内容
if result== false then return false end
jsonString=string.sub(jsonString,pos2+1,#jsonString) --记录下后面部分
pos1,_=string.find(jsonString,"%[")
if pos1 then
pos2,_ = string.find(jsonString,"%]")
if pos2 then
head=string.sub(jsonString,2,pos1-1)
local a,b=string.gsub(head,"(\"-)(.-)(\"-):","")
if a ~="" and b~=1 then return false end -- "head":[{....},{.....},{.....}] 其中的head格式不正确
head=string.sub(jsonString,pos1+1,pos2-1) --下一次循环传入的参数
else
return false--缺少]
end
else
return false --[]缺少[]
end
end
end
else
return false -- "head":[{....},{.....},{.....}] 其中的head格式不正确
end
else
return false --不匹配[]
end
else --没有中括号,简单的单个{}json处理
local result =ContinueCheck(String1)
if result then return true else return false end
end
else
return false --不匹配{}
end
end
function ContinueCheck(jsonString)
local stringLength=#jsonString
local pos1,pos2=0,0
local JsonTable={}
local i=1
while (true) do --截取{....}并且存入表JsonTable中
pos1,_=string.find(jsonString,"{",pos1+1)
if pos1 then
pos2,_=string.find(jsonString,"}",pos2+1)
if pos2 then
JsonTable[i]=string.sub(jsonString,pos1+1,pos2-1)
else
return false
end
else
return false
end
if pos2==#jsonString then break end
i=i+1
end
local a,b
local j=1
while (true) do
jsonString=JsonTable[j] --一个一个值检查
while (true) do
local q,_=string.find(jsonString,",")
if q~= nil then --"a":"i","b":"j"找这之间的逗号
local jsonString2=string.sub(jsonString,1,q-1) --,号前
jsonString=string.sub(jsonString,q+1,#jsonString) --,号后
a,b=string.gsub(jsonString2,"(\"-)(.-)(\"-):","")
else --没有则为key:value 的最后一个
a,b=string.gsub(jsonString,"(\"-)(.-)(\"-):","")
end
if b==1 then
a,b=string.gsub(a,"(\"-)(.+)(\"+)","")
if a=="" then
mSleep(10)
else
a=tonumber(a)
if type(a) == "number" then
mSleep(10)
else
return false
end
end
else
return false
end
if q == nil then --找到最后啦
break
end
end
if j==i then return true end
j=j+1
endend
其中msleep只是封装的等待,可以看出这样写的会嵌套超多层,也就我这种格式规范对的整整齐齐的才看得清,不过勉强作为上述简单的json判断还是没问题的,但是后来考虑到如果json有嵌套,一直嵌套[..]和{..}那要怎么办呢,明显这种从{..}中从前到后截取判断的方法是不实用的,然后又花了几天写了一个可以判断任意嵌套的封装函数,有点长还没做优化但是已经可以正常使用了,代码如下:
function ifIsJson(JsonString)
local pos1,pos2,pos3,pos4=0,0,0,0
local counter1,counter2,counter3,counter4=0,0,0,0
local string1,string2
local Mytable,Mytable2={},{}
local i,j=1,1
JsonString=JsonString:atrim()
string1=string.sub(JsonString,1,1)
string2=string.sub(JsonString,-1,-1)
if string1=="{" and string2=="}" then --查看各种括号是否成对存在
_,pos1=string.gsub(JsonString,"{","{")
_,pos2=string.gsub(JsonString,"}","}")
_,pos3=string.gsub(JsonString,"%[","[")
_,pos4=string.gsub(JsonString,"%]","]")
if pos1~=pos2 or pos3~=pos4 then return false end
else return false end
while (true) do
pos1,pos2=string.find(JsonString,",%[{",pos1)-- 找 ,[{ 找到后找 }]
if pos1 then
pos3,pos4=string.find(JsonString,"}]",pos4)
if pos3 then
string1=string.sub(JsonString,pos1,pos4)
_,counter1=string.gsub(string1,"{","{") --查看各种括号是否成对存在
_,counter2=string.gsub(string1,"}","}")
_,counter3=string.gsub(string1,"%[","[")
_,counter4=string.gsub(string1,"%]","]")
if counter1 == counter2 and counter3== counter4 then
Mytable[i]=string.sub(JsonString,pos2,pos3) --{....}
i=i+1
string1=string.sub(JsonString,1,pos1-1)
string2=string.sub(JsonString,pos4+1)
JsonString=string1..string2 -- 去掉,{[..}]
pos4=pos1
end
else return false end
else
pos1,pos2,pos3,pos4=1,1,1,1
pos1,pos2=string.find(JsonString,"%[{") --找[{ 找到后找 }]没有则跳出
if pos1 then
pos3,pos4=string.find(JsonString,"}]")
if pos3 then
string1=string.sub(JsonString,pos1,pos4)
_,counter1=string.gsub(string1,"{","{") --查看各种括号是否成对存在
_,counter2=string.gsub(string1,"}","}")
_,counter3=string.gsub(string1,"%[","[")
_,counter4=string.gsub(string1,"%]","]")
if counter1 == counter2 and counter3== counter4 then
Mytable[i]=string.sub(JsonString,pos2,pos3) --{....}
i=i+1
string1=string.sub(JsonString,1,pos1-1)
string2=string.sub(JsonString,pos4+1)
JsonString=string1.."\"\""..string2 -- 去掉,[{..}]
pos4=pos1
end
else return false end
else break end
end
end
i=i-1
if Mytable[i]~= nil then
pos1,pos2,pos3,pos4=1,1,1,1
while (true) do --截取嵌套n层的最里面的[{.....}]
repeat -- 找table[]中[{最靠后的这符号,
pos1,pos2=string.find(Mytable[i],"%[{",pos2)
if pos1 then pos3,pos4=pos1,pos2 end
until pos1==nil
pos1,pos2=string.find(Mytable[i],"}]",pos4) --找串中pos4之后}]最靠前的这个符号
if pos1 then
Mytable2[j]=string.sub(Mytable[i],pos4,pos1) --[ {....} ]
j=j+1
string1=string.sub(Mytable[i],1,pos3-1)
stirng2=string.sub(Mytable[i],pos2+1)
Mytable[i]=string1.."\"\""..string2
else
Mytable2[j]=Mytable[i]
j=j+1
i=i-1
if i== 0 then break end--直到找不到成对的[{}]
end
pos2=1
end
end
Mytable2[j]=JsonString
i=1
Mytable={}
pos1,pos2,pos3,pos4=0,0,1,1
while (true) do
repeat
pos1,_=string.find(Mytable2[j],"{",pos2+1)
if pos1 then pos2=pos1 end
until pos1 == nil
pos3,_=string.find(Mytable2[j],"}",pos2)
if pos3 and pos2~=1 then
Mytable[i]=string.sub(Mytable2[j],pos2,pos3) -- {...}
i=i+1
string1=string.sub(Mytable2[j],1,pos2-1)
string2=string.sub(Mytable2[j],pos3+1)
Mytable2[j]=string1.."\"\""..string2
else
Mytable[i]=string.sub(Mytable2[j],1,pos3)
i=i+1
j=j-1
if j==0 then break end
end
pos2=0
-- 串b截取 { "id":"243125b4-5cf9-4ad9-827b-37698f6b98f0" } 这样的格式 存进table[j]
-- 剩下一个 "image":{ "id":"243125b4-5cf9-4ad9-827b-37698f6b98f0","a":"e0", "d":"2431-f6b98f0","f":"243125b98f0"--}
这样的也存进table[j+1]
end
i=i-1
for n=1,i do --去除{}
Mytable[n]=string.sub(Mytable[n],2,-2)
end
while (true) do
pos1,_=string.find(Mytable[i],",")
if pos1~= nil then --"a":"i","b":"j"找这之间的逗号
string1=string.sub(Mytable[i],1,pos1-1)--,前
Mytable[i]=string.sub(Mytable[i],pos1+1)
pos2,_=string.find(string1,"\"")
if pos2==1 then
pos3,pos4=string.find(string1,"\":",2)
if pos3 then
string2=string.sub(string1,pos4+1)
else
--("发现错误1", 1)
return false
end
else
--("发现错误2", 1)
return false
end
else
pos2,_=string.find(Mytable[i],"\"")
if pos2==1 then
pos3,pos4=string.find(Mytable[i],"\":",2)
if pos3 then
string2=string.sub(Mytable[i],pos4+1)
else
--("发现错误3", 1)
return false
end
else
--("发现错误4", 1)
return false
end
end
pos2,pos3=string.gsub(string2,"(\"-)(.+)(\"+)","")
if pos2=="" or pos2 == "null" then
--("这一个串格式正确", 2)
else
pos2=tonumber(pos2)
if type(pos2) == "number" then
--("这一个串格式正确2", 2)
else
--("发现错误5", 1)
return false
end
end
if pos1== nil then
i=i-1
if i==0 then return true end
end
endend
这里有一个很核心的思想是既然是无限嵌套都要判断的出来,那么脚本要做到的是获取到最最里面的{..}单层结构的json,博猪是通过找最后的[ 和{ ,然后在此位置之后找最靠近的]和},截取出来后依然是按逗号截取出最小部分"a":"1"来判断格式,如果对你有帮助的话记得点赞哦~