cJSON的使用方法_cjson操作,一文说清

164 阅读5分钟

1. cJSON_CreateObject函数可创建一个根数据项,之后便可向该根数据项中添加string或int等内容,返回的是一个 cJSON的指针,注意,在这个指针用完了以后,需要手工调用 cJSON_Delete(root); 进行内存回收。

  1. cJSON_AddNumberToObject向节点中添加子节点,例如此处添加name节点,节点值为字符串"fengxin"

3. 需要注意的是  json 格式的数据,虽然也是一个字符串的样子,但这个时候还是无法当成普通的字符串进行使用,需要调用 cJSON_PrintUnformatted(root) 或者 cJSON_Print(root);来将json对象转换成普通的字符串,并且都是以该json对象的根为基点。两个API的区别即是:一个是没有格式的:也就是转换出的字符串中间不会有"\n" "\t"之类的东西存在,而cJSON_Print(root);打印出来是人看起来很舒服的格式。

  1. 因为函数内部封装有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;
}

   

收集整理了一份《2024年最新物联网嵌入式全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升的朋友。 img img

如果你需要这些资料,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人

都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!