OpenHarmony之cJSON库使用介绍
创始人
2025-05-30 17:38:52
0

一、前言

我们前面OpenHarmony设备配网 文章中,给大家提供的示例有使用cJSON解析和cJSON创建json数据的用法

那么有同学会提出疑问,我难道只能用cJSON库?

当然不是啊,你也可以用 json-parser、parson、jansson 等等三方库

回到正题,我们如何在OpenHarmony中,灵活熟练的使用cJSON库呢?

如果对JSON本身就不懂的,别急我们先带大家理解JSON,然后再去深入学习cJSON库的使用。

二、JSON理解

JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式。
JSON采用完全独立于语言的文本格式,但是也使用了类似于C语言家族的习惯(包括C, C++, C#, Java, JavaScript, Perl, Python等), 这些特性使JSON成为理想的数据交换语言。

我们可以在Be JSON中随便输入一个内容,查看报错的提示:

我们能看到期望的是如下格式的数据:

字符串、数字Number、NULL、BOOL、Json对象、Json数组,这些格式的数据


那么我们在JSON中,常用的(Json对象、Json数组) 2种数据格式:


Json对象

Json数组

1、Json对象

Json对象使用的是 { } 来描述,每个 Json 对象中都可以存储若干个元素,每一个元素都对应一个键值对(key:value 结构),元素和元素之间使用逗号间隔
key必须是字符串,value值类型可选,如:字符串、数字、Boolean、NULL、Json对象、Json数组

{"count": 100,"flag": true,"paras": {"Light": "ON","Motor": "OFF"}
}

2、Json数组

Json数组使用的是 [ ] 来描述,[ ]里面的元素和元素之间使用逗号间隔,支持的数据类型:字符串、数字、Boolean、NULL、Json对象、Json数组

// 整形
[996,2399,1999,6999]
// 字符串
["张三", "李四", "王二", "麻子"]
// 混合使用
[111, 9.99, true, false, "交个朋友", null]
// 数组嵌套,数组使用,用逗号分隔
[["张三", "李四", "王二", "麻子"],[111, 9.99, true, false, "兄弟们支持了吗?", null]
]
// 数组嵌套对象
[{"king": {"child": ["张三", "李四", "王二", "麻子"]}},[111, 9.99, true, false, "你好,陌生人", null]
]

三、cJSON详解

有了上面的知识,来看cJSON会发现,其实也很简单,没有那么难,只需要知道对应方法的含义和如何使用它,就能解决开发中遇到的问题了。

我们看cJSON数据结构如下

/* The cJSON structure: */
typedef struct cJSON
{struct cJSON *next;struct cJSON *prev;struct cJSON *child;int type;char *valuestring;/* writing to valueint is DEPRECATED, use cJSON_SetNumberValue instead */int valueint;double valuedouble;char *string;
} cJSON;

char *string:表示对象中的key
int type:用于描述数据元素的类型,type一共定义了 7种 类型。
如果获取的类型是:Number类型,使用valueint
如果获取的类型是:double类型,使用valuedouble
如果获取的类型是:string类型,使用valuestring

我们可以通过如下方法去检查type类型:

大家看一下,源码中,就是通过这种方式,去判断type类型,然后去获取最终的数据值的:

CJSON_PUBLIC(char *) cJSON_GetStringValue(cJSON *item) 
{if (!cJSON_IsString(item)) {return NULL;}return item->valuestring;
}
...
CJSON_PUBLIC(double) cJSON_GetNumberValue(cJSON *item) 
{if (!cJSON_IsNumber(item)) {return NAN;}return item->valuedouble;
}

1、如何创建一个JSON对象?

带着问题去看源码并寻找解决答案

// cJSON.h
/* These calls create a cJSON item of the appropriate type. */
CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void);
CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void);
CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void);
CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool boolean);
CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num);
CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string);
/* raw json */
CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw);
CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void);
CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void);

我们刚刚在上面介绍JSON的时候,知道JSON可以是如下几种类型的:

字符串、数字Number、NULL、BOOL、Json对象、Json数组

所以我们可以通过cJSON_Create... 来创建JSON对象。

那么创建完JSON对象之后,如何添加键值对呢?

// cJSON.h
CJSON_PUBLIC(cJSON*) cJSON_AddNullToObject(cJSON * const object, const char * const name);
CJSON_PUBLIC(cJSON*) cJSON_AddTrueToObject(cJSON * const object, const char * const name);
CJSON_PUBLIC(cJSON*) cJSON_AddFalseToObject(cJSON * const object, const char * const name);
CJSON_PUBLIC(cJSON*) cJSON_AddBoolToObject(cJSON * const object, const char * const name, const cJSON_bool boolean);
CJSON_PUBLIC(cJSON*) cJSON_AddNumberToObject(cJSON * const object, const char * const name, const double number);
CJSON_PUBLIC(cJSON*) cJSON_AddStringToObject(cJSON * const object, const char * const name, const char * const string);
CJSON_PUBLIC(cJSON*) cJSON_AddRawToObject(cJSON * const object, const char * const name, const char * const raw);
CJSON_PUBLIC(cJSON*) cJSON_AddObjectToObject(cJSON * const object, const char * const name);
CJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON * const object, const char * const name);

我们看下面这样的json应该如何使用cJSON?

{"pi": 3.141,"happy": true,"name": "头戴三叉束发紫金冠体挂西川红棉百花袍身披兽面吞头连环铠腰系勒甲玲珑狮蛮带手持方天画戟坐下嘶风赤兔马之吕小布是也"
}

使用方式:

int main()
{cJSON * root;// 创建根数据对象root=cJSON_CreateObject();// 添加键值对cJSON_AddBoolToObject(root,"happy",true);cJSON_AddNumberToObject(root,"pi",3.141);cJSON_AddNumberToObject(root,"name","头戴三叉束发紫金冠体挂西川红棉百花袍身披兽面吞头连环铠腰系勒甲玲珑狮蛮带手持方天画戟坐下嘶风赤兔马之吕小布是也"); // 将json形式转换成字符串char *out = cJSON_Print(root);printf("%s\n",out);// 释放内存,如果不删除会出现内存泄漏cJSON_Delete(root);  free(out);        
}

2、如何创建一个JSON数组?

看完上面的内容,我们应该知道应该用的是cJSON_CreateArray对吧。

假如我们有如下json内容:

[111, 9.99, true, false, "交个朋友", null]

使用方式:

int main()
{cJSON *root;root = cJSON_CreateArray();cJSON_AddItemToArray(root, cJSON_CreateNumber(111)); cJSON_AddItemToArray(root, cJSON_CreateNumber(9.99)); cJSON_AddItemToArray(root, cJSON_CreateBool(true));  cJSON_AddItemToArray(root, cJSON_CreateBool(false)); cJSON_AddItemToArray(root, cJSON_CreateString("交个朋友"));cJSON_AddItemToArray(root, cJSON_CreateNull());char *s = cJSON_PrintUnformatted(root);if(s){printf(" %s \n",s);free(s);}// 必须要删除,否则会出现内存泄漏cJSON_Delete(root);return 0;
}

3、如何创建一个JSON对象嵌套数组?

{"test":[{"name":"雷布斯","motto":"碉堡了,友商是傻瓜"}]
}

使用方式:

int main()
{cJSON *root, *body, *list;// json对象rootroot = cJSON_CreateObject();// root 添加键值对,test:json数组AcJSON_AddItemToObject(root,"test", body = cJSON_CreateArray());// json数组A,添加Json对象BcJSON_AddItemToArray(body, list = cJSON_CreateObject());// 在json对象B中添加键值对cJSON_AddStringToObject(list,"name","雷布斯");// 在json对象B中添加键值对cJSON_AddNumberToObject(list,"motto","碉堡了,友商是傻瓜");char *s = cJSON_PrintUnformatted(root);if(s){printf("%s \n",s);free(s);}if(root){// 必须要删除,否则会出现内存泄漏cJSON_Delete(root); }return 0;
}

4、如何解析json?

// cJSON.h
CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value);

将字符串转换为 cJSON 结构体

这里我们拿复杂的嵌套数据来讲解,json对象嵌套数组,如何解析呢?

{"list": [{"day": 1,"money": -1999999}, {"day": 10,"money": 1999999}]
}

我们看到,最外层是一个JSONObject
然后通过 key: list 获取JSONArray
JSONArray里面有2个JSONObject
然后通过 key: happykey: money 获取对应的值

int main()
{char *s = "{\"list\":[{\"day\":1,\"money\":-1999999},{\"day\":10,\"money\":1999999}]}";cJSON *root = cJSON_Parse(s);if(!root) {printf("cJSON_Parse失败 !\n");return -1;}cJSON *list = cJSON_GetObjectItem(root, "list");if(!list){printf("没有发现key为list的Item!\n");return -1;}// 这里我们需要获取数组的大小int array_size = cJSON_GetArraySize(list);printf("数组大小:%d\n",array_size);for(int i=0; i< array_size; i++) {// 获取JSONArraycJSON* item = cJSON_GetArrayItem(list, i);cJSON* day = cJSON_GetObjectItem(item, "day");printf("day is %d\n",day->valueint);cJSON* money = cJSON_GetObjectItem(item, "money");printf("money is %d\n",money->valueint);}if(root){// 删除JSON并释放内存cJSON_Delete(root);}return 0;
}

四、注意事项

刚刚上面我们介绍了,如何通过cJSON库:创建JSON以及如何解析JSON。

那么我们在cJSON解析数据的时候,一定要做数据健全性检查。

例如,我们刚写了下面2行代码:

cJSON *recvJson = cJSON_Parse(recvBuf);
cJSON *testID = cJSON_GetObjectItem(recvJson, "test_id");
...

我们这个时候能直接用testID吗? 肯定不能,我们需要检查一下它是否存在,可增加如下代码进行判断:

if(testID == NULL || testID->type == cJSON_NULL) 
{ printf("JSON数据有问题\r\n");
}
else 
{ // 这里做正常的业务处理...
}

这个时候可能有同学会疑问了,cJSON里面没有方法判断吗?

肯定有啊,请使用 cJSON_HasObjectItem

if(1 == cJSON_HasObjectItem(json,"test_id"))
{// 这里做正常的业务处理
}
else  
{printf("JSON数据有问题\r\n");
}

那么我们这个时候,假设使用的是 testID->valuestring 获取内容,需要判断是否和本地的一个字符串值 雷布斯 是否相等,我们应该如何做呢?

我们可以使用 strcmp 来比较2个数据值是否相等

if (strcmp(testIDValue, "雷布斯") == 0) 
{ // 这里判断2个数据值相等,这个分支里面写我们的业务代码...
}

相关内容

热门资讯

linux入门---制作进度条 了解缓冲区 我们首先来看看下面的操作: 我们首先创建了一个文件并在这个文件里面添加了...
C++ 机房预约系统(六):学... 8、 学生模块 8.1 学生子菜单、登录和注销 实现步骤: 在Student.cpp的...
JAVA多线程知识整理 Java多线程基础 线程的创建和启动 继承Thread类来创建并启动 自定义Thread类的子类&#...
【洛谷 P1090】[NOIP... [NOIP2004 提高组] 合并果子 / [USACO06NOV] Fence Repair G ...
国民技术LPUART介绍 低功耗通用异步接收器(LPUART) 简介 低功耗通用异步收发器...
城乡供水一体化平台-助力乡村振... 城乡供水一体化管理系统建设方案 城乡供水一体化管理系统是运用云计算、大数据等信息化手段࿰...
程序的循环结构和random库...   第三个参数就是步长     引入文件时记得指明字符格式,否则读入不了 ...
中国版ChatGPT在哪些方面... 目录 一、中国巨大的市场需求 二、中国企业加速创新 三、中国的人工智能发展 四、企业愿景的推进 五、...
报名开启 | 共赴一场 Flu... 2023 年 1 月 25 日,Flutter Forward 大会在肯尼亚首都内罗毕...
汇编00-MASM 和 Vis... Qt源码解析 索引 汇编逆向--- MASM 和 Visual Studio入门 前提知识ÿ...
【简陋Web应用3】实现人脸比... 文章目录🍉 前情提要🌷 效果演示🥝 实现过程1. u...
前缀和与对数器与二分法 1. 前缀和 假设有一个数组,我们想大量频繁的去访问L到R这个区间的和,...
windows安装JDK步骤 一、 下载JDK安装包 下载地址:https://www.oracle.com/jav...
分治法实现合并排序(归并排序)... 🎊【数据结构与算法】专题正在持续更新中,各种数据结构的创建原理与运用✨...
在linux上安装配置node... 目录前言1,关于nodejs2,配置环境变量3,总结 前言...
Linux学习之端口、网络协议... 端口:设备与外界通讯交流的出口 网络协议:   网络协议是指计算机通信网...
Linux内核进程管理并发同步... 并发同步并发 是指在某一时间段内能够处理多个任务的能力,而 并行 是指同一时间能够处理...
opencv学习-HOG LO... 目录1. HOG(Histogram of Oriented Gradients,方向梯度直方图)1...
EEG微状态的功能意义 导读大脑的瞬时全局功能状态反映在其电场结构上。聚类分析方法一致地提取了四种头表面脑电场结构ÿ...
【Unity 手写PBR】Bu... 写在前面 前期积累: GAMES101作业7提高-实现微表面模型你需要了解的知识 【技...