Linux_cJSON使用--数据封装与解析

一、JOSN的概念:

1.cJSON简介

  • JSON(JavaScript Object Notation)是一种轻量级的文本数据交换格式, 易于让人阅读。同时也易于机器解析和生成.。JSON虽然是Javascript的一个子集, 但JSON是独立于语言的文本格式,并且采用了类似C语言的一些习惯。
  • 为什么我们要使用cJSON呢? 我们在传输数据时, 如果只有一个数据比如温度t = 26.53 .我们传输过去一定会知道这个数据是什么。此时如果数据既有温度和湿度. 那么我们传输过去的是俩个字符串. 此时是不能分辨出温度还是湿度的值。而cJSON简洁又简单,而且效率又快,cJSON工程文件也非常简单,仅一个.C文件和一个.h文件!并且文件体积大小不到K。源码思路也非常清晰,也非常适合研究。

2.JSON 语法

cJSON 的格式为:{//花括号内保存对象
                      “sn”: “sds123”,//数据由逗号分隔 
                      “tem”:12.2,//名称在前,数据在冒号后面
                      “time”:13:00”
                }

3.cJSON下载(Linux环境下)

我们可以通过此链接下载cJOSN
https://sourceforge.net/projects/cjson/

当我们下载好cJSON只需要把.C文件和.h文件包含文件拷贝到我们工程目录下,我们就可以使用了。

4.cJSON的使用

4.1使用方法:

1.通过gcc直接编译 :
gcc test.c cjson.c

但每次编译两个文件有些麻烦,所以接下来,我们使用动态库。

2.动态库

这里我们不细讲动态库,想学习的可以参考下一篇博客。

gcc test.c -lcjson -L.

二.cJSON库函数的简介

1、cJSON *cJSON_CreateObject();
//创建一个json对象,返回一个cJSON结构体类型的指针。
2.void cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item);
//向json对象中添加一对元素,object为json对象,string为加入一对元素中的name,item为加入一对元素中的value。
3. cJSON_AddNumberToObject(json,"temp",30.56);
 //向json对象中添加一个数
4.cJSON *cJSON_CreateString(const char *string);
//创建一个字符串对象,传入一个char *类型的字符串,返回一个cJSON结构体类型的指针。

5.void cJSON_AddItemToArray(cJSON *array, cJSON *item);
//向数组对象中添加一个元素,传入参数array为cJSON *结构体类型的指针,为数组对象,item为添加如数字对象中的对象指针。

6.char *cJSON_Print(cJSON *item);
//将一个cJSON结构体代表的json对象转换为一个json格式的字符串。

7.void cJSON_Delete(cJSON *c)
//释放一个cJSON对象占用的内存空间。
 
 

三. cJSON函数库的使用

我以socket以客户端发送,服务器端接收解析为例:

客户端:

int main(int argc,char*argv[])
{
        int                       socket_fd=-1;
        struct sockaddr_in        serv_addr;
        int                       rv;
        char                      buf[1024];
        char                      *buff;
        FILE                      *fp;


         cJSON *json = cJSON_CreateObject();//创建一个json对象
         cJSON_AddItemToObject(json,"number",cJSON_CreateString("PRI001"));//向json中添加序列号
         cJSON_AddItemToObject(json,"time",cJSON_CreateString("2021-02-19 21:01:30"));//向json中添加日期
         cJSON_AddNumberToObject(json,"temp",30.56);//向json中添加温度值


        // buff = cJSON_Print(json);
         fp = fopen("create.json","w");
         fwrite(buff,strlen(buff),1,fp);
         buff = cJSON_Print(json);

        socket_fd=socket(AF_INET, SOCK_STREAM ,0);
        if(0>socket_fd)
        {
                printf("create socket failure:i'%s'\n",strerror(errno));
                return -1;
        }
        memset(&serv_addr,0,sizeof(serv_addr));
        serv_addr.sin_family=AF_INET;
        serv_addr.sin_port = htons(SERVER_PORT);
        inet_aton(SERVER_IP,&serv_addr.sin_addr);

        if(connect(socket_fd, (struct sockaddr *)&serv_addr,sizeof(serv_addr))<0)
        {
                printf("connect to server [%s:%d] failure:%s\n",SERVER_IP,SERVER_PORT,strerror(errno));
                return 0;
        }

 
        if( write(socket_fd,buff,strlen(buff))<0)
        {
                printf("cinnect to server[%s:%d] failure:'%s'\n",SERVER_IP,SERVER_PORT,strerror(errno));
                goto clearup;
        }

        memset(buf,0,sizeof(buf));
        rv=read(socket_fd,buf,sizeof(buf));
        if(0>rv)
        {
                printf("read data from server failure:'%s'\n",strerror(errno));
                goto clearup;
        }
        else if(0==rv)
        {
                printf("client connect to server get disconnected\n");
                goto clearup;
        }
        printf("raed:%d bety data from server:%s\n",rv,buf) ;
        //free(buff);
        fclose(fp);
        //释放json结构所占用的内存
        cJSON_Delete(json);

clearup:
       close(socket_fd);
}
 
                                                                                                                                            

服务器端:

 
 void print_usage(char *progname)
{
        printf("%s usage: \n", progname);
        printf("-p(--port): sepcify server listen PORT. \n");
        printf("-h(--help): printf this help information. \n");

        return ;
}

int main(int argc, char **argv)
{
        int                             sockfd = -1;  //socket 返回值
        int                             rv = -1;  //connect 返回值
        struct sockaddr_in      servaddr;  //
        struct sockaddr_in      cliaddr;  //
        socklen_t                       len;
        int                                     port = 0;
        int                                     clifd;
        char                            buf[1024];
        int                    i;
        int                   size;
        cJSON                 *tnode = NULL;
        cJSON                 *node = NULL;



        struct option           opts[] ={
                {"port", required_argument, NULL, 'p'},
                {"help", no_argument, NULL, 'h'},
                {NULL, 0, NULL, 0}
        };

        int                                     ch;
        printf("start parser agguments\n");
        while( (ch=getopt_long(argc, argv, "p:h", opts, NULL)) != -1)
        {
                switch(ch)
                {
                        case 'p':
                                port = atoi(optarg);
                                break;
                        case 'h':
                                print_usage(argv[0]);
                                break;
                }

        }

        if( !port)
        {
                print_usage(argv[0]);
                return 0;
        }

        //一个socket连接由四个元素组成:源ip,端口, 目的ip,端口
        //我们现在已经绑定了目的ip和端口. 源ip和端口并未指定
        //客户端如果想通过指定ip与端口来连接服务器,调用bind()
        //一般客户端不调用bind(), 这是操作系统内核会自动分配
        sockfd = socket(AF_INET, SOCK_STREAM, 0);
        if(sockfd < 0)
        {
                printf("Create socket failure: %s\n", strerror(errno));
                return -1;
        }
        printf("Create socket[%d] successfully!\n", sockfd);

        memset(&servaddr, 0, sizeof(servaddr));  //将结构体内存清零
        servaddr.sin_family=AF_INET;  //设置为IPv4.
        servaddr.sin_port = htons(port);  //注意:此处不能直接等于"12345", 这是本机字节序, 网络中传输的是网络字节序, 使用htons 转换, s是俩个字节的意思.
        servaddr.sin_addr.s_addr = htonl(INADDR_ANY);  //INADDR_ANY就是 0000
        //inet_aton(servip, &servaddr.sin_addr); // server:172.17.53.29 这样只监听这个IP ifconfig来的   正常的要监听所有IP
        //服务器一般只绑定端口, IP 设置为INADDR_ANY 监听所有IP.

        int on = 1;
        if((setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on))) < 0 )
        {
                perror("setsockopt failed");
                exit(EXIT_FAILURE);
        }
        rv=bind(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr));
        if(rv < 0)
        {
                printf("Socket [%d] bind on port[%d] failure: %s\n", sockfd, port, strerror(errno));
//              printf("create socket failure: %s\n", strerror(errno));
                return -2;
        }

        listen(sockfd, 13);  //backlog 是正处于连接客户端所保持的个数.
        printf("Start to listen on port [%d]!\n", port);
//      printf("Connect to server[%s:%d] successfully!\n",servip, port);

        while(1)
        {
                printf("Start caaept new client incoming...");
                clifd = accept(sockfd, (struct sockaddr *)&cliaddr, &len);
                if(clifd < 0)
                {
                        printf("Accept new client failure: %s\n", strerror(errno));
                        continue;
                }

                printf("Accept new client[%s:%d] successfully\n", inet_ntoa(cliaddr.sin_addr), ntohs(cliaddr.sin_port));

                memset(buf, 0, sizeof(buf));
                rv = read(clifd, buf, sizeof(buf));
                printf("111 buf:%s\n", buf);
                if( rv < 0 )
                {
                        printf("Read data from clien by sockfd[%d] failure: %s\n", clifd, strerror(errno));
                        close(clifd);
                        continue;
                }
                else if( rv == 0 )
                {
                        printf(" Clifd[%d] get disconnected\n", clifd);                                                                                                                     
                        break;
                }
                else if( rv > 0 )
                {

                       size = cJSON_GetArraySize(node);

                       for(i=0;i<size;i++)
                       {
                               tnode = cJSON_GetArrayItem(node,i);//json解析
                               if(tnode->type == cJSON_String)
                                {
                                        printf("value[%d]:%s\n",i,tnode->valuestring);
                                }
                               else
                                {
                                        printf("node' type is not string\n");
                                }
                       }
                }


                rv = write(clifd, MSG_STR, strlen(MSG_STR));
                if( rv < 0 )
                {
                        printf("Write to client by sockfd[%d] failure: %s\n", sockfd, strerror(errno));
                        close(clifd);
                        continue;
                }
                printf("Close client socket[%d]\n", clifd);
                close(clifd);
        }
        
}

                                                                                           
                                                   


评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值