博猪开了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"来判断格式,如果对你有帮助的话记得点赞哦~