cJSON解析器总结[转载]
一. 简介
cJson 是c语言编写的一个解析器. 是一个超轻巧,携带方便,单文件,简单的可以作为ANSI-C标准的JSON解析器。主要两个文件cJSON.c 和cJSON.h . 主要用来编码和解析数据.
其中,定义了一个cJSON的数据结构,用来储存数据.是以链表的形式.结构体如下:
在.h文件下
typedef struct cJSON { struct cJSON *next,*prev; //双向链表 struct cJSON *child; //指向字节点,主要是在数组结构中用 int type; //类型,有7种类型,也就是说可以储存7种形式数据 /*分别为: 1. cJSON_False 2. cJSON_True 3. cJSON_NULL 4. cJSON_Number 5. cJSON_String 6. cJSON_Array 7. cJSON_Object */ char *valuestring; // 如果类型为cJSON_String 时用来存那个字符串 int valueint; //如果类型为cJSON_Number 时用来存值 ,这个主要存int型,如果是小数会有类型转换 double valuedouble; //这个存浮点数,如果是整数也会转换为浮点型,和valueint一起存同一个数据 char *string; //用来存字节点名字.主要是object时用. } cJSON;
二. 把数据组织成结构(也就是节点组成结构)
下面的函数来产生各种类型的节点.
1 extern cJSON *cJSON_CreatNULL(void); 2 extern cJSON *cJSON_CreateTrue(void); 3 extern cJSON *cJSON_CreateFalse(void); 4 extern cJSON *cJSON_CreateBool(int b); 5 extern cJSON *cJSON_CreateNumber(double num); 6 extern cJSON *cJSON_CreateString(const char *string); 7 extern cJSON *cJSON_CreateArray(void); 8 extern cJSON *cJSON_CreateObject(void);
这些函数主要是把类型type写入节点,并且把相关的值也写入节点.比如创造字符串节点函数,还要把字符串指针valuestring指向相应字符串.
下面的函数创造数组节点集.也就是先创建一个数组类型的节点(用cJSON_CreateArray(void)函数 ),再把number数组的数据分别放在一个结点中(比如一个个int型数据的节点),并链表串起来(用suffix_object()函数).最后都悬挂在数组节点的字节点上(也就是结构体中的child指针指向它们),最后的最后返回数组的指针.
1 extern cJSON *cJSON_CreateIntArray(const int *numbers,int count); 2 extern cJSON *cJSON_CreateFloatArray(const float *numbers,int count); 3 extern cJSON *cJSON_CreateDoubleArray(const double *numbers,int count); 4 extern cJSON *cJSON_CreateStringArray(const char **strings,int count);
下面图例一个说明创建一个数型数组的过程:
三. 打包结构数据
组织好数据后就要已一定的格式把结构组织成字符串,便于传递. 使用函数:
1 extern char *cJSON_Print(cJSON *item);
2 extern char *cJSON_PrintUnformatted(cJSON *item);
说明:
如例子:
1 out=cJSON_Print(root); //就把结构root以一定的方式打包成字符串out.
分析一下打印的方式:
两种打印方式: 有格式和无格式两种;
cJSON_Print(root); 内部调用print_value(item,0, 1),而cJSON_PrintUnformatted(cJSON *item);内部调用print_value(item,0,0),
而print_value()函数里面分情况解析如下:
1 switch ((item->type)&255) 2 { 3 case cJSON_NULL: out=cJSON_strdup("null"); break; 4 case cJSON_False: out=cJSON_strdup("false");break; 5 case cJSON_True: out=cJSON_strdup("true"); break; 6 case cJSON_Number: out=print_number(item);break; 7 case cJSON_String: out=print_string(item);break; 8 case cJSON_Array: out=print_array(item,depth,fmt);break; 9 case cJSON_Object: out=print_object(item,depth,fmt);break; 10 }
所以对于数值, 字符串, 数组和object来说 ,又有各自的函数print_number和print_string 函数就是以一定方式储存成字符串.而 print_array 和 print_object 函数又是对上两个函数的封装.
一般再调用函数删除前面的结构:
1 extern void cJSON_Delete(cJSON *c);
如例子:
1 cJSON_Delete(root);
这样就把数据彻底打包完成,可以传递或储存了.
四. 解析,还原结构
其中有几个辅助函数,先介绍一下:
1 //得到数组的长度,也就是子节点的个数. 2 extern int cJSON_GetArraySize(cJSON *array); 3 //得到数组的第item个节点. 4 extern cJSON *cJSON_GetArrayItem(cJSON *array,int item); 5 //得到名为string的节点. 6 extern cJSON *cJSON_GetObjectItem(cJSON *object,const char *string);
解析采用分层解析的形式,一步一步解到最后一层.
和打印的方式一样,打印是:如果是数组或object , 则继续向下打印. 直到到子节点, 数值或字符串或其他,然后打印.. 解析应该正好相反. 比如最上层是数组, 那么先解析数组,然后得出数组大小, 再得出每一个数组节点, 如果不是最终节点. 还要往下: 先打印这个子节点,再解析,再得出子节点的子节点, 最后打印出来.就是节点的值了.
例子如下:
1 cJSON * root,*arrayItem,*item,*name,*path,*flag; 2 int i = 0,size = 0; 3 char *pr = NULL,*na = NULL,*pa = NULL,*fl = NULL; 4 //将字符串解析成json结构体 5 root = cJSON_Parse(out); 6 //根据结构体获取数组大小 7 size = cJSON_GetArraySize(root); 8 //printf("%d\n",size); 9 //遍历数组 10 for(i=0;i < size; i++) 11 { 12 //获取第i个数组项 13 arrayItem = cJSON_GetArrayItem(root,i); 14 if(arrayItem) 15 { 16 //printf("%s\n","start......"); 17 //讲json结构体转换成字符串 18 pr = cJSON_Print(arrayItem); 19 item = cJSON_Parse(pr); 20 name = cJSON_GetObjectItem(item,"name"); 21 path = cJSON_GetObjectItem(item,"path"); 22 flag = cJSON_GetObjectItem(item,"flag"); 23 na = cJSON_Print(name); 24 pa = cJSON_Print(path); 25 fl = cJSON_Print(flag); 26 //printf("%s\n",pr); 27 printf("name:%s\n",na); 28 printf("path:%s\n",pa); 29 printf("flag:%s\n\n",fl); 30 } 31 }
————————————————
版权声明:本文为CSDN博主「xz_free」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/ldk_0819/article/details/62215507