[转]使用cJSON解析JSON字符串

前端之家收集整理的这篇文章主要介绍了[转]使用cJSON解析JSON字符串前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

转自:http://www.jb51.cc/article/p-bqoatrju-gm.html

JSON学习-使用cJSON解析

使用cJSON解析JSON字符串

@L_502_2@一、为何选择cJSON

我们在使用JSON格式时,如果只是处理简单的协议,可以依据JSON格式,通过对字符串的操作来进行解析与创建。然而随着协议逐渐复杂起来,经常会遇到一些未考虑周全的地方,需要进一步的完善解析方法,此时,使用比较完善的JSON解析库的需求就提出来了。

基于方便引用的考虑,我们希望这个JSON解析库是用C语言实现的。同时,为了避免太过复杂的C源码包含关系,希望最好是一个C文件来实现。通过在网络上的查找,发现cJSON是比较符合要求的。cJSON只有一个C文件,一个头文件,包含到项目源码中非常方便,而且其实现效率也是非常高的。

二、cJSON的核心结构体

cJSON的核心结构体就是一个cJSON,理解了这个结构体,基本上对cJSON的使用就有了个基本概念了。该结构体具体定义如下:

typedef struct cJSON {

struct cJSON*next,*prev; /* 遍历数组或对象链的前向或后向链表指针*/

struct cJSON *child; /*数组或对象的孩子节点*/

int type; /* key的类型*/

char *valuestring; /*字符串值*/

int valueint; /* 整数值*/

double valuedouble; /* 浮点数值*/

char *string; /* key的名字*/

} cJSON;

说明:

1、cJSON是使用链表来存储数据的,其访问方式很像一颗树。每一个节点可以有兄弟节点,通过next/prev指针来查找,它类似双向链表;每个节点也可以有孩子节点,通过child指针来访问,进入下一层。只有节点是对象或数组时才可以有孩子节点。

2、type是键(key)的类型,一共有7种取值,分别是:False,Ture,NULL,Number,String,Array,Object。

若是Number类型,则valueint或valuedouble中存储着值。若期望的是int,则访问valueint,若期望的是double,则访问valuedouble,可以得到值。

若是String类型的,则valuestring中存储着值,可以访问valuestring得到值。

3、string中存放的是这个节点的名字,可理解为key的名称

三、解析JSON格式;

还是在Linux下,使用C语言编程,先实现读文件功能,然后开始JSON字符串的解析。我们还是一步步来,先从简单的开始,万丈高楼起于平地嘛。

1,下载源码;

可以从如下网站来下载:https://sourceforge.net/projects/cjson/

2,包含cJSON的源码;

下载下来,解压后,从里面找到两个文件(cJSON.c、cJSON.h),复制到我们的工程里面。只需在函数中包含头文件(#include “cJSON.h”),然后和cJSON.c一起编译即可使用。

3,解析一个键值对;

首先是一个简单的键值对字符串,要解析的目标如下:

{"firstName":"Brett"}

要进行解析,也就是要分别获取到键与值的内容。我们很容易就能看出键为firstName,值为Brett,可是,使用cJSON怎么解析呢?

对于这个简单的例子,只需要调用cJSON的三个接口函数就可以实现解析了,这三个函数的原型如下:

cJSON*cJSON_Parse(const char *value);

cJSON*cJSON_GetObjectItem(cJSON *object,const char *string);

voidcJSON_Delete(cJSON *c);

下面按解析过程来描述一次:

(1) 首先调用cJSON_Parse()函数,解析JSON数据包,并按照cJSON结构体的结构序列化整个数据包。使用该函数会通过malloc()函数在内存中开辟一个空间,使用完成需要手动释放。

cJSON*root=cJSON_Parse(json_string);

(2) 调用cJSON_GetObjectItem()函数,可从cJSON结构体中查找某个子节点名称(键名称),如果查找成功可把该子节点序列化到cJSON结构体中。

cJSON*item=cJSON_GetObjectItem(root,"firstName");

(3) 如果需要使用cJSON结构体中的内容,可通过cJSON结构体中的valueint和valuestring取出有价值的内容(即键的值)

本例子中,我们直接访问 item->valuestring 就获取到 "Brett" 的内容了。

(4) 通过cJSON_Delete(),释放cJSON_Parse()分配出来的内存空间。

cJSON_Delete(root);

这样就完成了一次cJSON接口调用,实现了解析工作。使用起来其实也很简单的啊,呵呵。

4,解析一个结构体;

接下来,我们来个复杂一点的,解析一个结构体,要解析的目标如下:

{

"person":

{

"firstName":"z",

"lastName":"jadena",

"email":"jadena@126.com",

"age":8,

"height":1.17

}

}

看起来比一个键值对复杂多了,我们又需要学习新的接口函数了吗?

答案是不需要!

还是那三个函数就可以了。当然,解析的步骤要复杂一些了,下面我按解析过程来描述一次:

(1)根据JSON串中的对象,我们定义一个相应的结构体如下:

typedefstruct

{

char firstName[32];

char lastName[32];

char email[64];

int age;

float height;

} PERSON;

具体的对应关系,一目了然,我就不罗嗦了。让我们直奔主题,解析!

(2)还是调用cJSON_Parse()函数,解析JSON数据包。

cJSON*root=cJSON_Parse(json_string);

(3)调用一次cJSON_GetObjectItem()函数获取到对象person。

cJSON *object=cJSON_GetObjectItem(root,"person");

(4)对我们刚取出来的对象person,多次调用cJSON_GetObjectItem()函数,来获取对象的成员。此时要注意,不同的成员,访问的方法不一样:

cJSON*item;

PERSONperson;

item=cJSON_GetObjectItem(object,"firstName");

memcpy(person.firstName,item->valuestring,strlen(item->valuestring));

item=cJSON_GetObjectItem(object,"lastName");

memcpy(person.lastName,"email");

memcpy(person.email,"age");

person.age=item->valueint;

item=cJSON_GetObjectItem(object,"height");

person.height=item->valuedouble;

这样,就获取到了对象的全部内容了。

(5) 通过cJSON_Delete(),释放cJSON_Parse()分配出来的内存空间。

cJSON_Delete(root);

至此,我们就使用cJSON接口完成了基于结构体的解析工作。

5,解析结构体数组的JSON串;

最后,我们来个更复杂一些的,来解析一个数组,并且数组的成员是结构体!要解析的JSON串如下:

{

"people":[

{"firstName":"z","lastName":"Jason","email":"bbbb@126.com","height":1.67},

{"lastName":"jadena","email":"jadena@126.com","age":8,"height":1.17},

{"email":"cccc@126.com","firstName":"z","lastName":"Juliet","age":36,"height":1.55}

]

}

此时,我们真的又需要学习新的接口了,一个是获取数组长度,一个是取数组成员,函数原型如下:

int cJSON_GetArraySize(cJSON *array);

cJSON*cJSON_GetArrayItem(cJSON *array,int item);

由于前面已经实现了结构体的解析,这里我们只需要关注下数组的相关调用即可。

(1)调用cJSON_Parse()函数,解析JSON数据包。

(2)调用一次cJSON_GetObjectItem()函数获取到数组people。

(3)对我们刚取出来的数组people,调用cJSON_GetArraySize()函数,来获取数组中对象的个数。然后,多次调用cJSON_GetArrayItem()函数,逐个读取数组中对象的内容

(4)通过cJSON_Delete(),释放cJSON_Parse()分配出来的内存空间。

这样,我们就使用cJSON接口完成了结构体数组的解析工作。

详细代码见后文附带例程。

说明:

本文所附带例程,实现了结构体数组的解析,只是一个学习之作,对于初学JSON使用cJSON接口的同学,可以有些借鉴参考的作用。

附带例程:

  1. #include<stdio.h>
  2. #include<string.h>
  3. #include<sys/types.h>
  4. #include<stdlib.h>
  5. #include<unistd.h>
  6. #include"cJSON.h"
  7. typedefstruct
  8. {
  9. intid;
  10. charfirstName[32];
  11. charlastName[32];
  12. charemail[64];
  13. intage;
  14. floatheight;
  15. }people;
  16. voiddofile(char*filename);/*Readafile,parse,renderback,etc.*/
  17. intmain(intargc,char**argv)
  18. {
  19. //dofile("json_str1.txt");
  20. //dofile("json_str2.txt");
  21. dofile("json_str3.txt");
  22. return0;
  23. }
  24. //parseakey-valuepair
  25. intcJSON_to_str(char*json_string,char*str_val)
  26. {
  27. cJSON*root=cJSON_Parse(json_string);
  28. if(!root)
  29. {
  30. printf("Errorbefore:[%s]\n",cJSON_GetErrorPtr());
  31. return-1;
  32. }
  33. else
  34. {
  35. cJSON*item=cJSON_GetObjectItem(root,"firstName");
  36. if(item!=NULL)
  37. {
  38. printf("cJSON_GetObjectItem:type=%d,keyis%s,valueis%s\n",item->type,item->string,item->valuestring);
  39. memcpy(str_val,strlen(item->valuestring));
  40. }
  41. cJSON_Delete(root);
  42. }
  43. return0;
  44. }
  45. //parseaobjecttostruct
  46. intcJSON_to_struct(char*json_string,people*person)
  47. {
  48. cJSON*item;
  49. cJSON*root=cJSON_Parse(json_string);
  50. if(!root)
  51. {
  52. printf("Errorbefore:[%s]\n",cJSON_GetErrorPtr());
  53. return-1;
  54. }
  55. else
  56. {
  57. cJSON*object=cJSON_GetObjectItem(root,"person");
  58. if(object==NULL)
  59. {
  60. printf("Errorbefore:[%s]\n",cJSON_GetErrorPtr());
  61. cJSON_Delete(root);
  62. return-1;
  63. }
  64. printf("cJSON_GetObjectItem:type=%d,object->type,object->string,object->valuestring);
  65. if(object!=NULL)
  66. {
  67. item=cJSON_GetObjectItem(object,stringis%s,valuestring=%s\n",item->valuestring);
  68. memcpy(person->firstName,strlen(item->valuestring));
  69. }
  70. item=cJSON_GetObjectItem(object,"lastName");
  71. if(item!=NULL)
  72. {
  73. printf("cJSON_GetObjectItem:type=%d,item->valuestring);
  74. memcpy(person->lastName,strlen(item->valuestring));
  75. }
  76. item=cJSON_GetObjectItem(object,"email");
  77. if(item!=NULL)
  78. {
  79. printf("cJSON_GetObjectItem:type=%d,item->valuestring);
  80. memcpy(person->email,"age");
  81. if(item!=NULL)
  82. {
  83. printf("cJSON_GetObjectItem:type=%d,valueint=%d\n",item->valueint);
  84. person->age=item->valueint;
  85. }
  86. else
  87. {
  88. printf("cJSON_GetObjectItem:getageFailed\n");
  89. }
  90. item=cJSON_GetObjectItem(object,"height");
  91. if(item!=NULL)
  92. {
  93. printf("cJSON_GetObjectItem:type=%d,valuedouble=%f\n",item->valuedouble);
  94. person->height=item->valuedouble;
  95. }
  96. }
  97. cJSON_Delete(root);
  98. }
  99. return0;
  100. }
  101. //parseastructarray
  102. intcJSON_to_struct_array(char*text,peopleworker[])
  103. {
  104. cJSON*json,*arrayItem,*item,*object;
  105. inti;
  106. json=cJSON_Parse(text);
  107. if(!json)
  108. {
  109. printf("Errorbefore:[%s]\n",cJSON_GetErrorPtr());
  110. }
  111. else
  112. {
  113. arrayItem=cJSON_GetObjectItem(json,"people");
  114. if(arrayItem!=NULL)
  115. {
  116. intsize=cJSON_GetArraySize(arrayItem);
  117. printf("cJSON_GetArraySize:size=%d\n",size);
  118. for(i=0;i<size;i++)
  119. {
  120. printf("i=%d\n",i);
  121. object=cJSON_GetArrayItem(arrayItem,i);
  122. item=cJSON_GetObjectItem(object,"firstName");
  123. if(item!=NULL)
  124. {
  125. printf("cJSON_GetObjectItem:type=%d,stringis%s\n",item->string);
  126. memcpy(worker[i].firstName,"lastName");
  127. if(item!=NULL)
  128. {
  129. printf("cJSON_GetObjectItem:type=%d,item->valuestring);
  130. memcpy(worker[i].lastName,"email");
  131. if(item!=NULL)
  132. {
  133. printf("cJSON_GetObjectItem:type=%d,item->valuestring);
  134. memcpy(worker[i].email,"age");
  135. if(item!=NULL)
  136. {
  137. printf("cJSON_GetObjectItem:type=%d,item->valueint);
  138. worker[i].age=item->valueint;
  139. }
  140. else
  141. {
  142. printf("cJSON_GetObjectItem:getageFailed\n");
  143. }
  144. item=cJSON_GetObjectItem(object,"height");
  145. if(item!=NULL)
  146. {
  147. printf("cJSON_GetObjectItem:type=%d,value=%f\n",item->valuedouble);
  148. worker[i].height=item->valuedouble;
  149. }
  150. }
  151. }
  152. for(i=0;i<3;i++)
  153. {
  154. printf("i=%d,firstName=%s,lastName=%s,email=%s,age=%d,height=%f\n",
  155. i,
  156. worker[i].firstName,
  157. worker[i].lastName,
  158. worker[i].email,
  159. worker[i].age,
  160. worker[i].height);
  161. }
  162. cJSON_Delete(json);
  163. }
  164. return0;
  165. }
  166. //Readafile,etc.
  167. voiddofile(char*filename)
  168. {
  169. FILE*f;
  170. intlen;
  171. char*data;
  172. f=fopen(filename,"rb");
  173. fseek(f,SEEK_END);
  174. len=ftell(f);
  175. fseek(f,SEEK_SET);
  176. data=(char*)malloc(len+1);
  177. fread(data,1,len,f);
  178. fclose(f);
  179. printf("readfile%scomplete,len=%d.\n",filename,len);
  180. //charstr_name[40];
  181. //intret=cJSON_to_str(data,str_name);
  182. //peopleperson;
  183. //intret=cJSON_to_struct(data,&person);
  184. peopleworker[3]={{0}};
  185. cJSON_to_struct_array(data,worker);
  186. free(data);
  187. }

猜你在找的Json相关文章