cJson的使用方法
学长讲了cJson的基础后,做一下整理,并从网上找了一些资料做深入理解。
一 JSON概念
cJSON,目前来说,就只有两个文件,一个cJSON.c,一个cJSON.h文件。使用的时候,自己创建好一个main.c文件后,将头文件include进去
- 编译时记得在末尾链接libm库
二 JSON结构体
typedef struct cJSON
{
struct cJSON *next,*prev;
struct cJSON *child;
int type;
char *valuestring;
int valueint;
double valuedouble;
char *string;
}cJSON;
- 说明:
- cJSON结构体是一个双向列表,并可以通过child指针访问下一层。
- type变量决定数据项类型(键的类型),数据项可以是字符串可以是整形,也可以是浮点型。
- 如果是整形值的话可从
valueint
- 如果是浮点型的话可从
valuedouble
取出 - 如果是字符串的话可从
valuestring
取出 - string可以理解为节点的名称,综合此处的第二点可以理解为“键”的名称
- cJSON作为Json格式的解析库,其主要功能无非就是构建和解析Json格式了,用途就是一端将要发送的数据已cjson形式封装,然后发送,另一端收到此数据后,还是按cjson形式解析,就得到想要的数据了。
三 封装成json形式
创建json数据串。这数据串,可能是对象,也可能是数组,也可能是它们的各种组合,其中再加上一些键值对。有一点要先说明:它们的组合,符合父子继承格式--这也是json数据串的特点。
- 创建一个对象,并向这个对象里添加字符串和整型键值:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include"cJSON.h"
int main(void)
{
cJSON *usr;
cJSON *arry;
usr=cJSON_CreateObject();//创建数据跟对象
cJSON_AddStringToObject(usr,"name","lala");//加入键值,加字符串
cJSON_AddStringToObject(usr,"passwd","123");//加入键值,加字符串
cJSON_AddNumberToObject(usr,"num",1);//加整数
char *out=cJSON_Print(usr);//生成适合阅读的JSON字符串
printf("%s\n",out);//打印
//释放内存,很重要!!
cJSON_Delete(usr);//释放JSON对象
free(out);//释放生成的字符串
}
![2018-08-14 09-28-19 的屏幕截图](/home/lala/图片/2018-08-14 09-28-19 的屏幕截图.png)
说明:
- cJSON_CreateObject函数可创建一个根数据项,之后便可向该根数据项中添加string或int等内容,返回的是一个 cJSON的指针,注意,在这个指针用完了以后,需要手工调用 cJSON_Delete(root); 进行内存回收。
- cJSON_AddNumberToObject向节点中添加子节点,例如此处添加name节点,节点值为字符串”fengxin”
- 需要注意的是 json 格式的数据,虽然也是一个字符串的样子,但这个时候还是无法当成普通的字符串进行使用,需要调用 cJSON_PrintUnformatted(root) 或者 cJSON_Print(root);来将json对象转换成普通的字符串,并且都是以该json对象的根为基点。两个API的区别即是:一个是没有格式的:也就是转换出的字符串中间不会有”\n” “\t”之类的东西存在,而cJSON_Print(root);打印出来是人看起来很舒服的格式。
- 因为函数内部封装有malloc函数,所以使用free函数释放被out占用的内存空间
- 创建一个数组,并向数组添加一个字符串和一个数字:
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_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;
}
![2018-08-14 09-43-14 的屏幕截图](/home/lala/图片/2018-08-14 09-43-14 的屏幕截图.png)
- 对象里面包括一个数组,数组里面包括对象,对象里面再添加一个字符串和一个数字:
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_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;
}
![2018-08-14 09-51-01 的屏幕截图](/home/lala/图片/2018-08-14 09-51-01 的屏幕截图.png)
只要搞清楚父子关系即可
四 解析json得到的数据
解析数据包的过程和组装数据包的过程相反
解析JSON(JSON字符串转结构体)
处理流程:
1.现将普通的json串处理成json对象,也就是所谓的创建json root的过程
cJSON *root;
root=cJSON_Parse(js_string);//将JSON字符串转化为cJSON对象
2.开始拿关键字,但如果关键字还有父层或者祖层,那就需要先从父层开拿,所谓剥洋葱是也!
先说没有父层的:
out={\"name\":\"fengxin\",\"passwd\":\"123\",\"num\":1};
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include"cJSON.h"
int main(void)
{
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);
}
![2018-08-14 10-11-02 的屏幕截图](/home/lala/图片/2018-08-14 10-11-02 的屏幕截图.png)
上面的type 已经在cJSON.h里面定义好了,有自己的意义。如果是在严格的场所,应该先判定该 item的type,然后再考虑去拿值。
处理这串数据:
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 failed !\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;
}
![2018-08-14 10-25-30 的屏幕截图](/home/lala/图片/2018-08-14 10-25-30 的屏幕截图.png)
综合例子:
#include <stdio.h>
#include <math.h>
#include "./cJSON.h"
#include <stdlib.h>
#include <string.h>
struct student
{
int id;
char no[9] ;
char s_name[20];
};
int main(){
//创建JSON
struct student f = {1,"04163002","fujie"};
cJSON *student = cJSON_CreateObject();//创建数据根对象
cJSON_AddNumberToObject(student,"id",f.id);// 添加节点(属性)
/*
cJSON * id = cJSON_CreateNumber(f.id);
cJSON_AddItemToObject(student,"id",item);
*/
cJSON_AddStringToObject(student,"no",f.no);
cJSON_AddStringToObject(student,"s_name",f.s_name);
char *out = cJSON_Print(student); // 生成适合阅读的JSON字符串
printf("适合阅读:\n %s\n",out);
free(out); // 释放生成的字符串
out = cJSON_PrintUnformatted(student);// 生成适合传输的JSON字符串
printf("\n适合传输:\n %s\n",out);
// free(out);
cJSON_Delete(student);// 释放内存
//解析JSON
struct student ff;
cJSON *student2 = cJSON_Parse(out);
ff.id = cJSON_GetObjectItem(student2,"id")->valueint;
strcpy(ff.no,cJSON_GetObjectItem(student2,"no")->valuestring);
strcpy(ff.s_name,cJSON_GetObjectItem(student2,"s_name")->valuestring);
cJSON_Delete(student2);
free(out);
printf("\n解析结果: \n id: %d\n no: %s\n s_name: %s\n",ff.id,ff.no,ff.s_name);
}