cJSON的使用方法

首先,要介绍一下什么是json格式。linux

一.JSON格式简述json


JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式。易于人阅读和编写,同时也易于机器解析和生成。它基于JavaScript(Standard ECMA-262 3rd Edition - December 1999)的一个子集。 JSON采用彻底独立于语言的文本格式,可是也使用了相似于C语言家族的习惯(包括C, C++, C#, Java, JavaScript, Perl, Python等)。这些特性使JSON成为理想的数据交换语言。(来自“开源中国”资料)。数组

cJSON从名字可知,整个项目都是以极标准的C来写的,意思说,能够跨各类平台使用了。cJSON是一个超轻巧,携带方便,单文件,简单的能够做为ANSI-C标准的JSON解析器。函数

cJSON 开源项目位置:点击打开连接
更加详细的解释和示例请查看 http://www.json.org/ 主页。.net

cJSON,目前来讲,就只有两个文件,一个cJSON.c 一个cJSON.h文件。使用的时候,本身建立好一个main.c文件后,将头文件include进去。
若是是在linux pc上,请使用如下命令进行编译:
gcc *.c cJSON.c -lm指针

记得编译时末尾连接libm库。orm


二.JSON结构体
熟悉使用cJSON库函数可从cJSON结构体入手,cJSON结构体以下所示:
typedef struct cJSON {
struct cJSON *next,*prev;
struct cJSON *child;
int type;
char *valuestring;
int valueint;
double valuedouble;
char *string;
} cJSON; 对象

 

几点说明blog

1.cJOSN结构体为一个双向列表,并可经过child指针访问下一层。
2.type变量决定数据项类型(键的类型),数据项能够是字符串能够是整形,也能够是浮点型。若是是整形值的话可从valueint,若是是浮点型的话可从valuedouble取出,以此类推。
3.string可理解为节点的名称,综合此处的第2点可理解为“键”的名称。继承

cJSON做为Json格式的解析库,其主要功能无非就是构建和解析Json格式了,用途就是一端将要发送的数据已cjson形式封装,而后发送,另外一端收到此数据后,仍是按cjson形式解析,就获得想要的数据了。

三.封装成json形式
接下来直接经过几个例子代码,一一解析。
   
第一,建立json数据串。这数据串,多是对象,也多是数组,也多是它们的各类组合,其中再加上一些键值对。有一点要先说明:它们的组合,符合父子继承格式--这也是json数据串的特色。
<1>建立一个对象,并向这个对象里添加字符串和整型键值:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include"cJSON.h"

int main()
{
cJSON * usr;
cJSON *arry;

usr=cJSON_CreateObject(); //建立根数据对象
cJSON_AddStringToObject(usr,"name","fengxin"); //加入键值,加字符串
cJSON_AddStringToObject(usr,"passwd","123");
cJSON_AddNumberToObject(usr,"num",1); //加整数

char *out = cJSON_Print(usr); //将json形式打印成正常字符串形式
printf("%s\n",out);

// 释放内存
cJSON_Delete(usr);
free(out);


}

 


运行结果:
{
"name": "fengxin",
"passwd": "123",
"num": 1
}

若干说明

1. cJSON_CreateObject函数可建立一个根数据项,以后即可向该根数据项中添加string或int等内容,返回的是一个 cJSON的指针,注意,在这个指针用完了之后,须要手工调用 cJSON_Delete(root); 进行内存回收。
2. cJSON_AddNumberToObject向节点中添加子节点,例如此处添加name节点,节点值为字符串"fengxin"
3. 须要注意的是  json 格式的数据,虽然也是一个字符串的样子,但这个时候仍是没法当成普通的字符串进行使用,须要调用 cJSON_PrintUnformatted(root) 或者 cJSON_Print(root);来将json对象转换成普通的字符串,而且都是以该json对象的根为基点。两个API的区别便是:一个是没有格式的:也就是转换出的字符串中间不会有"\n" "\t"之类的东西存在,而cJSON_Print(root);打印出来是人看起来很舒服的格式。
4. 由于函数内部封装有malloc函数,因此使用free函数释放被out占用的内存空间

<2> 建立一个数组,并向数组添加一个字符串和一个数字:
int create_js(void)
{
cJSON *root, *js_body;
root = cJSON_CreateArray();
cJSON_AddItemToArray(root, cJSON_CreateString("Hello world"));
cJSON_AddItemToArray(root, cJSON_CreateNumber(10));
{
// char *s = cJSON_Print(root);
char *s = cJSON_PrintUnformatted(root);
if(s){
printf(" %s \n",s);
free(s);
}
}
if(root)
cJSON_Delete(root);

return 0;

}

int main(int argc, char **argv)
{
create_js();
return 0;
}

 

运行结果:
["Hello world",10]

<3> 对象里面包括一个数组,数组里面包括对象,对象里面再添加一个字符串和一个数字:
int create_js(void)
{
cJSON *root, *js_body, *js_list;
root = cJSON_CreateObject();
cJSON_AddItemToObject(root,"body", js_body = cJSON_CreateArray());
cJSON_AddItemToArray(js_body, js_list = cJSON_CreateObject());
cJSON_AddStringToObject(js_list,"name","fengxin");
cJSON_AddNumberToObject(js_list,"status",100);

{
// char *s = cJSON_Print(root);
char *s = cJSON_PrintUnformatted(root);
if(s){
printf(" %s \n",s);
free(s);
}
}
if(root)
cJSON_Delete(root);

return 0;
}

int main(int argc, char **argv)
{
create_js();
return 0;
}


运行结果:
{"body":[{"name":"fengxin","status":100}]}

<4>其余组合就依次类推,只要搞清楚父子关系便可。随便嵌套随便玩。再也不贴了。


四.解析json获得数据
解析数据包的过程和组装数据包的过程相反
处理流程:

1, 先将普通的json串处理成json对象,也就是所谓的建立json root的过程,只有一行代码便可:

cJSON *root;
root = cJSON_Parse(js_string);

2,开始拿关键字,但若是关键字还有父层或者祖层,那就须要先从父层开拿,所谓剥洋葱是也!

先说没有父层的:

out={\"name\":\"fengxin\",\"passwd\":\"123\",\"num\":1}


#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include"cJSON.h"

int main()
{
cJSON *json,*json_name,*json_passwd,*json_num;
char* out="{\"name\":\"fengxin\",\"passwd\":\"123\",\"num\":1}";

json = cJSON_Parse(out); //解析成json形式
json_name = cJSON_GetObjectItem( json , "name" ); //获取键值内容
json_passwd = cJSON_GetObjectItem( json , "passwd" );
json_num = cJSON_GetObjectItem( json , "num" );

printf("name:%s,passwd:%s,num:%d\n",json_name->valuestring,json_passwd->valuestring,json_num->valueint);

cJSON_Delete(json); //释放内存
free(out);



}

 


显示结果:
name:fengxin,passwd:123,num:1


须要注意的是: 上面的type 已经在cJSON.h里面定义好了,有本身的意义。若是是在严格的场所,应该先断定该 item的type,而后再考虑去拿值。

而若是有父层的话,无非就是接着向下拿就是了


3.处理这串数据:
out={\"list\":{\"name\":\"xiao hong\",\"age\":10},\"other\":{\"name\":\"hua hua\"}}

char *s = "{\"list\":{\"name\":\"xiao hong\",\"age\":10},\"other\":{\"name\":\"hua hua\"}}";
cJSON *root = cJSON_Parse(s);
if(!root) {
printf("get root faild !\n");
return -1;
}

cJSON *js_list = cJSON_GetObjectItem(root, "list");
if(!js_list) {
printf("no list!\n");
return -1;
}
printf("list type is %d\n",js_list->type);

cJSON *name = cJSON_GetObjectItem(js_list, "name");
if(!name) {
printf("No name !\n");
return -1;
}
printf("name type is %d\n",name->type);
printf("name is %s\n",name->valuestring);

cJSON *age = cJSON_GetObjectItem(js_list, "age");
if(!age) {
printf("no age!\n");
return -1;
}
printf("age type is %d\n", age->type);
printf("age is %d\n",age->valueint);

cJSON *js_other = cJSON_GetObjectItem(root, "other");
if(!js_other) {
printf("no list!\n");
return -1;
}
printf("list type is %d\n",js_other->type);

cJSON *js_name = cJSON_GetObjectItem(js_other, "name");
if(!js_name) {
printf("No name !\n");
return -1;
}
printf("name type is %d\n",js_name->type);
printf("name is %s\n",js_name->valuestring);

if(root)
cJSON_Delete(root);
return 0;


打印结果:
list type is 6
name type is 4
name is xiao hong
age type is 3
age is 10
list type is 6
name type is 4
name is hua hua


所谓子子孙孙无穷尽也,按照上面那个方法推下去便可。

4.json 里数组怎么取?
{\"list\":[\"name1\",\"name2\"]}

int main(int argc, char **argv)
{
char *s = "{\"list\":[\"name1\",\"name2\"]}";
cJSON *root = cJSON_Parse(s);
if(!root) {
printf("get root faild !\n");
return -1;
}
cJSON *js_list = cJSON_GetObjectItem(root, "list");
if(!js_list){
printf("no list!\n");
return -1;
}
int array_size = cJSON_GetArraySize(js_list);
printf("array size is %d\n",array_size);
int i = 0;
cJSON *item;
for(i=0; i< array_size; i++) {
item = cJSON_GetArrayItem(js_list, i);
printf("item type is %d\n",item->type);
printf("%s\n",item->valuestring);
}

if(root)
cJSON_Delete(root);
return 0;
}


5.若是json数组里面又搞了对象怎么办? 

不怕搞对象,就怕这样搞对象? 无他,就是稍微复杂了一点,全是体力活儿:

<1> 既然是数组里面,那确定要先测量数组的大小,而后根据大小循环拿;

<2> 拿到一个数组项,而后把这个项先转化成普通的json字符串,也就是 char *s 能接受的。

<3>再次将这个json字符串,转化成一个json对象

<4> 按照拿普通对象中的东西那样开干就好了。

 

{\"list\":[{\"name\":\"xiao hong\",\"age\":10},{\"name\":\"hua hua\",\"age\":11}]}

list 是一个数组,数组里面有两个对象,那么代码以下

int main(int argc, char **argv){char *s = "{\"list\":[{\"name\":\"xiao hong\",\"age\":10},{\"name\":\"hua hua\",\"age\":11}]}";cJSON *root = cJSON_Parse(s);if(!root) { printf("get root faild !\n"); return -1;}cJSON *js_list = cJSON_GetObjectItem(root, "list");if(!js_list){ printf("no list!\n"); return -1;}int array_size = cJSON_GetArraySize(js_list);printf("array size is %d\n",array_size);int i = 0;cJSON *item,*it, *js_name, *js_age;char *p = NULL;for(i=0; i< array_size; i++) { item = cJSON_GetArrayItem(js_list, i); if(!item) { //TODO... } p = cJSON_PrintUnformatted(item); it = cJSON_Parse(p); if(!it) continue ; js_name = cJSON_GetObjectItem(it, "name"); printf("name is %s\n",js_name->valuestring); js_age = cJSON_GetObjectItem(it, "age"); printf("age is %d\n",js_age->valueint); } if(root) cJSON_Delete(root); return 0;}

相关文章
相关标签/搜索