发现json类的一个bug
上次在《跟我一起学微信公众平台开发(二)》里提供了json类,今天发现有个bug,当属性值里有“:”“,”时,解析程序会出错,这两个符号是我们解析程序里字符串的起始判定符号,所以必须替换掉才可以进行解析。用上次的类,运行下面的代码将会报错!
程序代码:
CLEAR RELEASE ALL PUBLIC ojson *script=[{ "errcode": 0, "errmsg": "ok", "quota":{ "daily_limit": 0, "used": 0, "remain": 0}}] script=[{"errcode":40164,"errmsg":"invalid ip 112.10.181.255 ipv6 ::ffff:112.10.181.255, not in whitelist rid: 676ee36c-33ea19f9-5885a393"}] ojson=NEWOBJECT("json","myclass") ojson.parse(script) ?ojson.getvalue("errmsg")
解决方案很简单,就是判断每对“”的里面文字是否有“:”“,”,如果有就用“& # 58”“& # 44”替换,最后再复原就可以了。
主要代码如下:
json.parse
程序代码:
LPARAMETERS jsonscript *!* 12/28发现bug,当json属性的值里有“:”“,”符号时,解析程序出错 *!* 解决方案,解析前搜索每对引号对,把这两个字符替换掉,最后再复原。 LOCAL ckey,cstr,i,j,n,ccontent,ckey,cvalue,atemp,nleft,nright,jsarray,ncount,m jsonscript=STRTRAN(jsonscript,CHR(9),"") &&清除tab键 jsonscript=STRTRAN(jsonscript,CHR(10),"") &&清除ctrl+enter jsonscript=STRTRAN(jsonscript,CHR(13),"") &&清除换行符 jsonscript=allt(jsonscript) &&清除首尾空格 *!* ************最基本的json结构检查************ IF OCCURS("{",jsonscript)<>OCCURS("}",jsonscript) OR OCCURS("[",jsonscript)<>+OCCURS("]",jsonscript) OR MOD(OCCURS(["],jsonscript),2)<>0 MESSAGEBOX('{,[" 未成对!') RETURN .f. ENDIF *!* 12/28修改,加入代码完成对“:”(:)“,”(,)字符的判断并替换 ncount=0 n=OCCURS(["],jsonscript) FOR i=1 TO n/2 ccontent=STREXTRACT(jsonscript,["],["],2*i-1) *!* 替换“:” ncount=OCCURS([:],ccontent) IF ncount<>0 ctemp=STRTRAN(ccontent,[:],"& # 58") jsonscript=STRTRAN(jsonscript,ccontent,ctemp) ENDIF *!* *!* 替换“,” ccontent=STREXTRACT(jsonscript,["],["],2*i-1) ncount=OCCURS([,],ccontent) IF ncount<>0 ctemp=STRTRAN(ccontent,[,],"& # 44") jsonscript=STRTRAN(jsonscript,ccontent,ctemp) ENDIF *!* ENDFOR *!* this.jsscript=jsonscript ***** *!* 先检查是不是包含json数组的复合结构 *!* 提取所有json数组,并以AJSON+编号予以替换,保存于jsonarraylist中 n=0 DO WHILE .t. IF OCCURS("[",jsonscript)>0 &&说明json结构里有数组 DIMENSION jsonarraylist[n+1] &&用以保存json数组的内容 nleft =AT("[",jsonscript) &&确定第一个 "[" 的位置 i=0 *!* 下面这段代码确定与第一个 "[" 匹配的 "]" 的位置 DO WHILE .t. i=i+1 nright=AT("]",jsonscript,i) ccontent=SUBSTR(jsonscript,nleft,nright-nleft+1) IF OCCURS("[",ccontent)<>OCCURS("]",ccontent) LOOP ELSE EXIT ENDIF ENDDO *!* *!* ccontent=SUBSTR(jsonscript,nleft,nright-nleft+1) &&提取json数组的整体内容 n=n+1 jsarray="AJSON_"+TRANSFORM(n) &&准备替换掉数组的内容 jsonscript=STRTRAN(jsonscript,ccontent,jsarray) jsonarraylist(n)=ccontent LOOP ELSE *!* 2024/12.22 漏掉一种可能,没有数组,但是有json嵌套 IF OCCURS("{",jsonscript)>1 DIMENSION jsonarraylist[n+1] nleft=AT("{",jsonscript,2) nright=AT("}",jsonscript,1) ccontent=SUBSTR(jsonscript,nleft,nright-nleft+1) n=n+1 jsarray="OJSON_"+TRANSFORM(n) jsonscript=STRTRAN(jsonscript,ccontent,jsarray) jsonarraylist(n)=ccontent loop ELSE EXIT ENDIF *!* ENDIF ENDDO *!* *!* 对替换所有数组后的json结构进行解析 DIMENSION atemp[1] ncount=ALINES(atemp,jsonscript,9,",") FOR i=1 TO ncount ckey =ALLTRIM(STREXTRACT(STREXTRACT(atemp[i],"",":"),["],["])) cvalue=STRtr(STREXTRACT(atemp[i],":",""),["],[]) cvalue=ALLTRIM(STRTRAN(cvalue,"}","")) *!* 12/28加入,复原可能存在的“:”,“,” cvalue=STRTRAN(cvalue,"& # 44",[,]) cvalue=STRTRAN(cvalue,"& # 58",[:]) *!* this.Add(cvalue,ckey) ENDFOR *!* *!* *!* 如果是复合结构,则复原json数组内容 *!* IF VARTYPE(jsonarraylist)!="U" *!* FOR i=1 TO ALEN(jsonarraylist) *!* cvalue="AJSON_"+TRANSFORM(i) *!* FOR j=1 TO this.count *!* IF TRANSFORM(this.Item(j))=cvalue *!* ckey=this.GetKey(j) *!* this.Remove(ckey) *!* this.add(jsonarraylist[i],ckey) *!* ENDIF *!* ENDFOR *!* ENDFOR *!* ENDIF *!* *!* *!* 如果是复合结构,则复原json数组内容 IF VARTYPE(jsonarraylist)!="U" FOR i=1 TO ALEN(jsonarraylist) cvalue="AJSON_"+TRANSFORM(i) m=this.count FOR j=1 TO m IF TRANSFORM(this.Item(j))=cvalue ckey=this.GetKey(j) this.Remove(ckey) &ckey=NEWOBJECT([jsonarray],[myclass]) &ckey..name=ckey &ckey..parse(jsonarraylist[i]) IF j=m this.add(&ckey,ckey) ELSE this.Add(&ckey,ckey,j) ENDIF ENDIF ENDFOR ENDFOR FOR i=1 TO ALEN(jsonarraylist) cvalue="OJSON_"+TRANSFORM(i) m=this.count FOR j=1 TO m IF TRANSFORM(this.Item(j))=cvalue ckey=this.GetKey(j) this.Remove(ckey) &ckey=NEWOBJECT([json],[myclass]) &ckey..name=ckey &ckey..parse(jsonarraylist[i]) IF j=m this.add(&ckey,ckey) ELSE this.Add(&ckey,ckey,j) ENDIF ENDIF ENDFOR ENDFOR ENDIF *!*
json.getvalue代码也要稍作修改
程序代码:
PARAMETERS ckey,noccurrence LOCAL i,j,nleft,nright,cchar,cvalue,n cvalue="" IF PARAMETERS()=1 noccurrence=1 ENDIF n=AT(ckey,this.jsscript,noccurrence) IF n>0 *!* 确定指定json属性的值的起始位置 nleft=n+LEN(ckey) DO WHILE .t. nleft=nleft+1 cchar=SUBSTR(this.jsscript,nleft,1) IF cchar=":" nleft=nleft+1 &&从":"后面一个字符开始 EXIT ELSE LOOP ENDIF ENDDO *!* DO WHILE .t. cchar=ALLTRIM(SUBSTR(this.jsscript,nleft,1)) IF cchar=" " &&空格,冒号后面可能不小心输入了空格,剔除它 nleft=nleft+1 LOOP ELSE EXIT ENDIF ENDDO IF cchar="[" &&说明是数组 *!*确定与"["匹配的"]"的位置 i=0 DO WHILE .t. i=i+1 nright=AT("]",this.jsscript,i) IF nright<nleft LOOP ELSE cvalue=SUBSTR(this.jsscript,nleft,nright-nleft+1) IF OCCURS("[",cvalue)=OCCURS("]",cvalue) EXIT ELSE LOOP ENDIF ENDIF ENDDO ELSE &&否则就是普通数值 *!* 亦有可能是json嵌套,2024/12/22 加入json嵌套解读代码 IF cchar="{" &&说明值是一个json结构,然后找出“}”的位置 nright=nleft DO WHILE .t. nright=nright+1 cchar=SUBSTR(this.jsscript,nright,1) IF cchar="}" cvalue=SUBSTR(this.jsscript,nleft,nright-nleft+1) EXIT ELSE LOOP ENDIF ENDDO ELSE &&然后才是普通数值 cscript=this.jsscript+"," j=0 DO WHILE .t. j=j+1 nright=AT(",",cscript,j) IF nright<nleft LOOP ELSE cvalue=SUBSTR(cscript,nleft,nright-nleft) cvalue=STRTRAN(cvalue,["],"") cvalue=STRTRAN(cvalue,[}],"") cvalue=ALLTRIM(cvalue) *!* 12/28加入,复原可能的“:”“,” cvalue=STRTRAN(cvalue,"& # 44",",") cvalue=STRTRAN(cvalue,"& # 58",":") *!* EXIT ENDIF ENDDO ENDIF *!* ENDIF ENDIF RETURN cvalue
运行结果:
[此贴子已经被作者于2024-12-28 13:04编辑过]