| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 224 人关注过本帖
标题:跟我一起学微信公众平台开发(二)
只看楼主 加入收藏
sam_jiang
Rank: 9Rank: 9Rank: 9
等 级:贵宾
威 望:14
帖 子:808
专家分:1231
注 册:2021-10-13
结帖率:96.83%
收藏
 问题点数:20 回复次数:8 
跟我一起学微信公众平台开发(二)
不好意思,因为不是全职程序员,没有及时更新,这篇虽是第二篇,但是跟微信公众号没有关系,只能算是番外篇。。。
这篇主要是讲如何用foxpro写json解析程序,纯vfp代码,没有dll,fll库~
由于对于你的请求微信公众号返回的是json格式的,所以了解json格式是必须的。

主要思路:
1,把json结构看做一个collection,ckey就是json的属性;cvalue就是json的属性值,json的属性不可重复。
2,构建一个数组类jsonarray,对应于json的数组,数组的元素可以是任意值,也可以是json本身。
3,json类有3个重要的方法,
    a),json.parse 解析json
    b),json.generate 生成json脚本
    c),json.getvalue 根据给定的属性名返回属性值,如果值是数组,则返回整个数组的脚本。
4,使用add方法,添加属性及属性值
5,使用remove方法,删除属性及属性值
类代码如下:
程序代码:
**************************************************
*-- 类:           json (d:\documents\visual foxpro 项目\myclass.vcx)
*-- 父类:  collection
*-- 基类:    collection
*-- 时间戳:   12/21/24 09:19:08 PM
*
DEFINE CLASS json AS collection


    Height = 23
    Width = 23
    *-- 生成的json脚本
    jsscript = ""
    Name = "json"


    *-- 返回json结构中指定属性的值。
    PROCEDURE getvalue
        PARAMETERS ckey,noccurrence

        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 &&否则就是普通数值
                j=0
                DO WHILE .t.
                    j=j+1
                    nright=AT(",",this.jsscript,j)
                    IF nright<nleft
                        LOOP
                    ELSE
                        cvalue=SUBSTR(this.jsscript,nleft,nright-nleft)
                        cvalue=STRTRAN(cvalue,["],"")
                        cvalue=STRTRAN(cvalue,[}],"")
                        cvalue=ALLTRIM(cvalue)
                        EXIT
                    ENDIF
                ENDDO
            ENDIF
        ENDIF

        RETURN cvalue
    ENDPROC


    *-- 解析json结构。
    PROCEDURE parse
        LPARAMETERS jsonscript
        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

        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 
                EXIT
            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,"}",""))
            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 
        ENDIF
        *!*
    ENDPROC


    *-- 生成json脚本
    PROCEDURE generate
        LOCAL cscript,ckey,cvalue,oref,i
        cscript=""
        IF this.Count>0
            FOR i=1 TO this.Count
                ckey=this.GetKey(i)
                IF VARTYPE(this.Item(i))="O"
                    oref=this.Item(i)
                    cvalue=oref.generate()
                ELSE
                    cvalue=this.Item(i)
                ENDIF
                cscript=cscript+["]+ckey+[":]+IIF(LEFT(TRANSFORM(cvalue),1)="[",TRANSFORM(cvalue),["]+TRANSFORM(cvalue)+["])+","
            ENDFOR 
            cscript=[{]+SUBSTR(cscript,1,LEN(cscript)-1)+[}]
        ENDIF
        this.jsscript=cscript
        RETURN this.jsscript
    ENDPROC


    PROCEDURE Init
    ENDPROC


ENDDEFINE
*
*-- EndDefine: json
**************************************************


6,由于vfp不支持数组嵌套,所以就设计了一个数组类jsonarray,以便做到嵌套数组。
7,提供2两个重要的方法,
    a),jsonarray.parse 解析json数组
    b),jsonarray.generate 生成json数组脚本
    另外提供了一组操作数组的函数,add,remove,copy,item,clear,set

类代码如下:
程序代码:
**************************************************
*-- 类:           jsonarray (d:\documents\visual foxpro 项目\myclass.vcx)
*-- 父类:  custom
*-- 基类:    custom
*-- 时间戳:   12/21/24 10:50:10 PM
*
DEFINE CLASS jsonarray AS custom


    *-- Jsonarray数组成员数量。
    count = 0
    *-- json数组脚本
    script = ""
    Name = "jsonarray"

    *-- Jsonarray数组
    DIMENSION array[1]


    *-- 添加数组成员。
    PROCEDURE add
        LPARAMETERS eExpr
        this.count= this.count + 1
        dimension this.array[this.count]
        this.array[this.count] = eExpr
        return
    ENDPROC


    *-- 访问数组成员。
    PROCEDURE item
        LPARAMETERS n
        return this.array[n]
    ENDPROC


    *-- 移除数组成员。
    PROCEDURE remove
        LPARAMETERS eExpr

        IF TYPE(eExpr)="N"
            ADEL(this.array,eExpr)
            DIMENSION this.array(this.count-1)
            this.count=this.count-1
        ELSE 
            n=ASCAN(this.array,eExpr)
            IF n!=0
                ADEL(this.array,n)
                DIMENSION this.array(this.count-1)
                this.count=this.count-1
            ENDIF
        ENDIF


    ENDPROC


    *-- 清空数组。
    PROCEDURE clear
        DIMENSION this.array[1]
        this.array[1]=.f.
        this.count=0
    ENDPROC


    *-- 生成json数组文本。
    PROCEDURE generate
        LOCAL oref,cvalue,i,cexpression
        cexpression=""
        IF this.count<>0
            FOR i=1 TO this.count
                IF VARTYPE(this.item(i))="O"
                    oref=this.item(i)
                    cvalue=oref.generate()
                ELSE
                    cvalue=this.item(i)
                ENDIF

                IF [{] $ cvalue
                    cexpression=cexpression+cvalue+[,]
                ELSE
                    cexpression=cexpression+["]+cvalue+["]+[,]
                ENDIF
            ENDFOR 
            cexpression="["+LEFT(cexpression,LEN(cexpression)-1)+"]"
        ENDIF 
        this.script=cexpression
        RETURN this.script
    ENDPROC


    *-- 从已知数组复制。
    PROCEDURE copy
        PARAMETERS carrayname
        *调用该方法时数组变量参数前需加强制引用符号@
        n=ALEN(carrayname)
        DIMENSION this.array(n)
        FOR i=1 TO n 
            this.array(i)=carrayname(i)
        ENDFOR
        this.count=n
    ENDPROC


    *-- 设置数组项的值。
    PROCEDURE set
        PARAMETERS nindex,eExpr

        this.array[nindex]=eExpr


    ENDPROC


    *-- 解读json数组结构。
    PROCEDURE parse
        PARAMETERS cjsonarray
        LOCAL jsonobjectlist,nleft,right,i,ctemp,n,ii,ncount,nindex,oref
        *****
        ***** 先检查是不是包含json结构的复合数组
        *****
        this.script=cjsonarray
        DIMENSION jsonobjectlist[1]
        n=0
        DO WHILE .t.
            IF OCCURS("{",cjsonarray)>0 &&说明数组里有嵌套json结构
                DIMENSION jsonobjectlist[2*n+2] &&用以保存可能的json结构
                nleft=AT("{",cjsonarray)
                i=0
                DO WHILE .t.
                    i=i+1
                    nright=AT("}",cjsonarray,i)
                    ctemp=SUBSTR(cjsonarray,nleft,nright-nleft+1)
                    IF OCCURS("{",ctemp)<>OCCURS("}",ctemp)
                        LOOP
                    ELSE 
                        EXIT
                    ENDIF
                ENDDO
                *!* 将json数组中的json结构用OJSON_开头的字符串替换,并保存在数组中
                cjsonarray=STRTRAN(cjsonarray,ctemp,"OJSON_"+TRANSFORM(n+1))
        *!*            oref="OJSON_"+TRANSFORM(n+1)
        *!*            &oref=NEWOBJECT([json],[myclass])
                jsonobjectlist[2*n+1]="OJSON_"+TRANSFORM(n+1)
        *!*            jsonobjectlist[2*n+1]=&oref
                jsonobjectlist[2*n+2]=ctemp
        *!*            &oref..parse(ctemp)
                n=n+1
                *!*
                LOOP
            ELSE 
                EXIT &&没有json结构则退出循环。
            ENDIF
        ENDDO

        ncount=ALINES(this.array,cjsonarray,9,[,])
        FOR ii=1 TO ncount
            this.array[ii]=STRTRAN(this.array(ii),CHR(13),[])
            this.array[ii]=STRTRAN(this.array(ii),CHR(9),[])
            this.array[ii]=STRTRAN(this.array(ii),CHR(10),[])
            this.array[ii]=STRTRAN(this.array(ii),["],[])
            this.array[ii]=STRTRAN(this.array(ii),"[",[])
            this.array[ii]=STRTRAN(this.array(ii),"]",[])
            this.array[ii]=ALLTRIM(this.array[ii])
        ENDFOR 

        *!*    *!* 复原json数组里的json结构
        *!*    IF ALEN(jsonobjectlist)>1
        *!*        FOR j=1 TO ALEN(jsonobjectlist) STEP 2
        *!*            nindex=ASCAN(this.array,jsonobjectlist[j])
        *!*            this.array[nindex]=jsonobjectlist[j+1]
        *!*        ENDFOR 
        *!*    ENDIF 
        *!*    *!*

        *!* 复原json数组里的json结构
        IF ALEN(jsonobjectlist)>1
            FOR j=1 TO ALEN(jsonobjectlist) STEP 2
                nindex=ASCAN(this.array,jsonobjectlist[j])
                oref=this.array[nindex]
                &oref=NEWOBJECT([json],[myclass])
                this.array[nindex]=&oref
                &oref..name=oref
                &oref..parse(jsonobjectlist[j+1])
        *!*            this.array[nindex]=jsonobjectlist[j+1]
            ENDFOR 
        ENDIF 
        *!*

        this.count=ncount
    ENDPROC


ENDDEFINE
*
*-- EndDefine: jsonarray
**************************************************


8,附上测试代码,你们可能需要适当修改,我这两个类是保存在myclass里面的。
程序代码:
*jsontest.prg*
PUBLIC cjscript,ojson
CLEAR
cjscript=''
SET TEXTMERGE TO memvar cjscript noshow

\ {
\        "test":123,
\        "button":[
\     {    
\          "type":"click",
\          "name":"今日歌曲",
\          "key":"V1001_TODAY_MUSIC",
\          "array":[111,"aaa","bbb"]
\      },
\      {
\           "name":"菜单",
\           "sub_button":[
\           {    
\               "type":"view",
\               "name":"搜索",
\               "url":"http://www.\            },
\            {
\                 "type":"miniprogram",
\                 "name":"wxa",
\                 "url":"http://mp.weixin.,
\                 "appid":"wx286b93c14bbf93aa",
\                 "pagepath":"pages/lunar/index"
\             },
\            {
\               "type":"click",
\               "name":"赞一下我们",
\               "key":"V1001_GOOD"
\            }],
\            "test":[111,222,333]    
\       }],
\     "additive":"123456"
\ }
SET TEXTMERGE TO 
ojson=NEWOBJECT("json","myclass")
*!*    ojson.jsscript=cjscript
*!*    ?cjscript
*!*    *?EMPTY(ojson.getvalue("hello",4))

ojson.jsscript=cjscript
ojson.parse(cjscript)

cscript=ojson.getvalue("button")
ojsa=NEWOBJECT([jsonarray],[myclass])
ojsa.parse(cscript)
?ojsa.generate()

*!*    FOR i=1 TO ojson.count
*!*        ?ojson.getkey(i)
*!*        ? "___"
*!*        IF VARTYPE(ojson(i))="O"
*!*            ?ojson(i).script
*!*        else    
*!*            ?ojson(i)
*!*        ENDIF    
*!*    ENDFOR 

*!*    ?ojson.getvalue("sub_button",2)


运行环境:win7+vfp9.0(7423),本机编译通过。

[此贴子已经被作者于2024-12-21 23:15编辑过]

收到的鲜花
  • kangss昨天 13:28 送鲜花  1朵  
搜索更多相关主题的帖子: array count 数组 this IF 
前天 23:05
schtg
Rank: 12Rank: 12Rank: 12
来 自:Usa
等 级:贵宾
威 望:67
帖 子:1792
专家分:3409
注 册:2012-2-29
收藏
得分:0 
谢谢分享!
昨天 06:10
sych
Rank: 6Rank: 6
等 级:侠之大者
威 望:7
帖 子:322
专家分:450
注 册:2019-10-11
收藏
得分:0 
非常棒!谢谢分享
昨天 09:16
小白到底白不
Rank: 2
等 级:论坛游民
帖 子:70
专家分:54
注 册:2024-4-7
收藏
得分:0 
看看,学习一下,谢谢分享

小白到底白不白?知识很空白,脸有点黄,眼睛是黑的,血是红的,心肠算是比较热。
昨天 09:16
sam_jiang
Rank: 9Rank: 9Rank: 9
等 级:贵宾
威 望:14
帖 子:808
专家分:1231
注 册:2021-10-13
收藏
得分:0 
刚发现json类的getvalue有个bug,碰巧取最后一个属性的值时会出错,所以给出解决方案,大伙自行更改一下。。。

代码如下
......
    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)
......

[此贴子已经被作者于2024-12-22 10:07编辑过]

昨天 10:06
sam_jiang
Rank: 9Rank: 9Rank: 9
等 级:贵宾
威 望:14
帖 子:808
专家分:1231
注 册:2021-10-13
收藏
得分:0 
我把类的源代码打包发上来吧,之前有网友私信问我要源代码。

解压后把2个文件名分别改成myclass.vcx和myclass.vct就可以使用了。

@schtg ,@jsddx
myclass.zip (56.17 KB)
昨天 14:48
wcx_cc
Rank: 9Rank: 9Rank: 9
等 级:贵宾
威 望:52
帖 子:388
专家分:1202
注 册:2015-10-2
收藏
得分:0 
有楼主这样的高才和觉悟,值得大大称赞!收藏啦!!
昨晚 20:53
sam_jiang
Rank: 9Rank: 9Rank: 9
等 级:贵宾
威 望:14
帖 子:808
专家分:1231
注 册:2021-10-13
收藏
得分:0 
回复7楼
谢谢,你们的表扬是我不断奉献的动力

[此贴子已经被作者于2024-12-22 21:32编辑过]

昨晚 21:25
schtg
Rank: 12Rank: 12Rank: 12
来 自:Usa
等 级:贵宾
威 望:67
帖 子:1792
专家分:3409
注 册:2012-2-29
收藏
得分:0 
回复 6楼 sam_jiang
谢谢!
1 小时前
快速回复:跟我一起学微信公众平台开发(二)
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.331229 second(s), 12 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved