admin 管理员组文章数量: 1086019
2024年12月27日发(作者:实例方法如何调用静态方法)
使用cJSON解析JSON字符串
使用cJSON解析JSON字符串
一、为何选择cJSON
我们在使用JSON格式时,如果只是处理简单的协议,可以依据J
SON格式,通过对字符串的操作来进行解析与创建。然而随着协议逐
渐复杂起来,经常会遇到一些未考虑周全的地方,需要进一步的完善
解析方法,此时,使用比较完善的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,则访问value
double,可以得到值。
若是String类型的,则valuestring中存储着值,可以访问value
string得到值。
3、string中存放的是这个节点的名字,可理解为key的名称。
三、解析JSON格式;
还是在Linux下,使用C语言编程,先实现读文件的功能,然后
开始JSON字符串的解析。我们还是一步步来,先从简单的开始,万
丈高楼起于平地嘛。
1,下载源码;
可以从如下网站来下载: 。
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 *stri
ng);
voidcJSON_Delete(cJSON *c);
下面按解析过程来描述一次:
(1) 首先调用cJSON_Parse()函数,解析JSON数据包,并
按照cJSON结构体的结构序列化整个数据包。使用该函数会通过mal
loc()函数在内存中开辟一个空间,使用完成需要手动释放。
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":"**************",
"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()函数,获取到对象pers
on。
cJSON *object=cJSON_GetObjectItem(root,"person");
(4)对我们刚取出来的对象person,多次调用cJSON_GetObj
ectItem()函数,来获取对象的成员。此时要注意,不同的成员,访问
的方法不一样:
cJSON*item;
PERSONperson;
item=cJSON_GetObjectItem(object,"firstName");
memcpy(ame,item->valuestring,strlen(item->v
aluestring));
item=cJSON_GetObjectItem(object,"lastName");
memcpy(me,item->valuestring,strlen(item->v
aluestring));
item=cJSON_GetObjectItem(object,"email");
memcpy(,item->valuestring,strlen(item->value
string));
item=cJSON_GetObjectItem(object,"age");
=item->valueint;
item=cJSON_GetObjectItem(object,"height");
=item->valuedouble;
这样,就获取到了对象的全部内容了。
(5) 通过cJSON_Delete(),释放cJSON_Parse()分配出来
的内存空间。
cJSON_Delete(root);
至此,我们就使用cJSON接口完成了基于结构体的解析工作。
5,解析结构体数组的JSON串;
最后,我们来个更复杂一些的,来解析一个数组,并且数组的成
员是结构体!要解析的JSON串如下:
{
"people":[
{"firstName":"z","lastName":"Jason","email":"***********
m","height":1.67},
{"lastName":"jadena","email":"**************","age":8,"he
ight":1.17},
{"email":"************","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()函数,获取到数组peop
le。
(3)对我们刚取出来的数组people,调用cJSON_GetArraySiz
e()函数,来获取数组中对象的个数。然后,多次调用cJSON_GetArra
yItem()函数,逐个读取数组中对象的内容。
(4)通过cJSON_Delete(),释放cJSON_Parse()分配出来的内
存空间。
这样,我们就使用cJSON接口完成了结构体数组的解析工作。
详细代码见后文附带例程。
说明:
本文所附带例程,实现了结构体数组的解析,只是一个学习之作,
对于初学JSON使用cJSON接口的同学,可以有些借鉴参考的作用。
附带例程:
1.
2.
3.
4.
5.
6.
7.
8.
#include
#include
#include
#include
#include
#include "cJSON.h"
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
typedef struct
{
int id;
char firstName[32];
char lastName[32];
char email[64];
int age;
float height;
}people;
void dofile(char *filename);
/* Read a file, parse, re
int main(int argc, char **argv)
{
nder back, etc. */
//
//
dofile("json_");
dofile("json_");
dofile("json_");
return 0;
}
//parse a key-value pair
int cJSON_to_str(char *json_string, char *str_val)
{
cJSON *root=cJSON_Parse(json_string);
if (!root)
{
printf("Error before: [%s]n",cJSON_GetErrorPtr());
38.
39.
40.
41.
42.
me");
43.
44.
45.
46.
luestring));
47.
48.
49.
50.
51.
52.
53.
54.
son)
55.
56.
57.
58.
59.
60.
61.
62.
63.
return -1;
}
else
{
cJSON *item=cJSON_GetObjectItem(root,"firstNa
if(item!=NULL)
{
printf("cJSON_GetObjectItem: type=%d, key is %s,
memcpy(str_val,item->valuestring,strlen(item->va
}
cJSON_Delete(root);
}
return 0;
}
value is %sn",item->type,item->string,item->valuestring);
//parse a object to struct
int cJSON_to_struct(char *json_string, people *per
{
cJSON *item;
cJSON *root=cJSON_Parse(json_string);
if (!root)
{
printf("Error before: [%s]n",cJSON_GetErrorPtr());
return -1;
}
else
64.
65.
n");
66.
67.
68.
69.
70.
71.
72.
g);
73.
74.
75.
76.
77.
78.
79.
g);
80.
81.
82.
83.
84.
85.
86.
{
cJSON *object=cJSON_GetObjectItem(root,"perso
if(object==NULL)
{
printf("Error before: [%s]n",cJSON_GetErrorPtr());
cJSON_Delete(root);
return -1;
}
printf("cJSON_GetObjectItem: type=%d, key is %s,
value is %sn",object->type,object->string,object->valuestrin
if(object!=NULL)
{
item=cJSON_GetObjectItem(object,"firstName");
if(item!=NULL)
{
printf("cJSON_GetObjectItem: type=%d, string is %
s, valuestring=%sn",item->type,item->string,item->valuestrin
memcpy(person->firstName,item->valuestring,str
}
item=cJSON_GetObjectItem(object,"lastName");
if(item!=NULL)
{
printf("cJSON_GetObjectItem: type=%d, string is %
len(item->valuestring));
s, valuestring=%sn",item->type,item->string,item->valuestrin
g);
87.
88.
89.
90.
91.
92.
93.
g);
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
memcpy(person->email,item->valuestring,strlen(i
}
item=cJSON_GetObjectItem(object,"age");
if(item!=NULL)
{
printf("cJSON_GetObjectItem: type=%d, string is %
person->age=item->valueint;
}
else
{
printf("cJSON_GetObjectItem: get age failedn");
}
item=cJSON_GetObjectItem(object,"height");
if(item!=NULL)
{
tem->valuestring));
memcpy(person->lastName,item->valuestring,strl
}
item=cJSON_GetObjectItem(object,"email");
if(item!=NULL)
{
printf("cJSON_GetObjectItem: type=%d, string is %
en(item->valuestring));
s, valuestring=%sn",item->type,item->string,item->valuestrin
s, valueint=%dn",item->type,item->string,item->valueint);
111.
uble);
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
er[])
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
printf("cJSON_GetObjectItem: type=%d, string is %
s, valuedouble=%fn",item->type,item->string,item->valuedo
person->height=item->valuedouble;
}
}
cJSON_Delete(root);
}
return 0;
}
//parse a struct array
int cJSON_to_struct_array(char *text, people work
{
cJSON *json,*arrayItem,*item,*object;
int i;
json=cJSON_Parse(text);
if (!json)
{
printf("Error before: [%s]n",cJSON_GetErrorPtr());
}
else
{
arrayItem=cJSON_GetObjectItem(json,"people");
if(arrayItem!=NULL)
{
int size=cJSON_GetArraySize(arrayItem);
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
g);
156.
157.
158.
159.
160.
161.
162.
printf("cJSON_GetArraySize: size=%dn",size);
for(i=0;i { printf("i=%dn",i); object=cJSON_GetArrayItem(arrayItem,i); item=cJSON_GetObjectItem(object,"firstName"); if(item!=NULL) { printf("cJSON_GetObjectItem: type=%d, string is % memcpy(worker[i].firstName,item->valuestring,str } item=cJSON_GetObjectItem(object,"lastName"); if(item!=NULL) { printf("cJSON_GetObjectItem: type=%d, string is % sn",item->type,item->string); len(item->valuestring)); s, valuestring=%sn",item->type,item->string,item->valuestrin memcpy(worker[i].lastName,item->valuestring,strl } item=cJSON_GetObjectItem(object,"email"); if(item!=NULL) { printf("cJSON_GetObjectItem: type=%d, string is % en(item->valuestring)); s, valuestring=%sn",item->type,item->string,item->valuestrin g); 163. 164. 165. 166. 167. 168. 169. 170. 171. 172. 173. 174. 175. 176. 177. 178. 179. 180. 181. 182. 183. 184. 185. 186. 187. memcpy(worker[i].email,item->valuestring,strlen(i } item=cJSON_GetObjectItem(object,"age"); if(item!=NULL) { printf("cJSON_GetObjectItem: type=%d, string is % worker[i].age=item->valueint; } else { printf("cJSON_GetObjectItem: get age failedn"); } item=cJSON_GetObjectItem(object,"height"); if(item!=NULL) { printf("cJSON_GetObjectItem: type=%d, string is % worker[i].height=item->valuedouble; } } } for(i=0;i<3;i++) { tem->valuestring)); s, valueint=%dn",item->type,item->string,item->valueint); s, value=%fn",item->type,item->string,item->valuedouble); 188. 189. 190. 191. 192. 193. 194. 195. 196. 197. 198. 199. 200. 201. 202. 203. 204. 205. 206. 207. 208. 209. 210. 211. 212. 213. 214. 215. 216. printf("i=%d, firstName=%s,lastName=%s,email=% i, worker[i].firstName, worker[i].lastName, worker[i].email, worker[i].age, worker[i].height); } cJSON_Delete(json); } return 0; } s,age=%d,height=%fn", // Read a file, parse, render back, etc. void dofile(char *filename) { FILE *f; int len; char *data; f=fopen(filename,"rb"); fseek(f,0,SEEK_END); len=ftell(f); fseek(f,0,SEEK_SET); data=(char*)malloc(len+1); fread(data,1,len,f); fclose(f); 217. len); 218. 219. 220. 221. 222. 223. 224. 225. 226. 227. 228. 229. printf("read file %s complete, len=%d.n",filename, // // char str_name[40]; int ret = cJSON_to_str(data, str_name); people person; int ret = cJSON_to_struct(data, &person); // // people worker[3]={{0}}; cJSON_to_struct_array(data, worker); free(data); }
版权声明:本文标题:使用cJSON解析JSON字符串 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://roclinux.cn/p/1735336950a1649994.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论