OpenHarmony之cJSON库使用介绍
一、前言
我们前面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: happy
、key: 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个数据值相等,这个分支里面写我们的业务代码...
}
相关文章:

OpenHarmony之cJSON库使用介绍
一、前言 我们前面OpenHarmony设备配网 文章中,给大家提供的示例有使用cJSON解析和cJSON创建json数据的用法 那么有同学会提出疑问,我难道只能用cJSON库? 当然不是啊,你也可以用 json-parser、parson、jansson 等等三方库 回到正题…...

门面设计模式
介绍 Java门面模式(Facade Pattern)是一种结构型设计模式,它提供了一个简单的接口,隐藏了复杂系统的实现细节,使得客户端可以更加容易地使用系统. 在Java门面模式中,一个门面对象(Facade)提供了一个简单的接口,该接口包装了一个或多个复杂的子系统,客户端可以直接使用门面对象…...

苹果手写笔好用吗?比较好用的ipad手写笔推荐
随着技术的进步,各种新型的电子产品和数码器件层出不穷。比如智能手机、IPAD、以及电容笔。而在实际生活中,为了更好的利用ipad,我们需要一支好用的电容笔。就好比如我们在ipad上做笔记,要用手来进行手写记录,会很不方…...

GPT-4来了!看看她究竟强在哪里!
GPT-4来了!OpenAI老板Sam Altman直接开门见山地介绍说:这是我们迄今为止功能最强大的模型!GPT-4是一个超大的多模态模型,也就是说,它的输入可以是文字(上限2.5万字),还可以是图像。我…...

GPT-4 API 接口调用及价格分析
GPT-4 API 接口调用及价格分析 15日凌晨,OpenAI发布了万众期待的GPT-4!新模型支持多模态,具备强大的识图能力,并且推理能力和回答准确性显著提高。在各种专业和学术基准测试上的表现都媲美甚至超过人类。难怪OpenAI CEO Sam Altm…...

MySQL高级功能:存储过程、触发器、事务、备份和恢复
MySQL高级功能MySQL是一款广泛使用的关系型数据库管理系统,它不仅具有基本的数据库功能,还支持一些高级功能,如存储过程、触发器、事务、备份和恢复等。这些高级功能可以帮助开发人员更高效地管理和维护数据库,本文将介绍MySQL的高…...

SAP 发出商品业务配置
SAP发出商品业务配置,即: 出具销售发票时结转成本 一、业务背景: 发出商品业务简单的理解为跨月开票,即出库与开票不在同一个月份。 该业务在系统内的实现方式,为保证成本与收入的配比,在出库时不计算成…...

C++线程池理解
线程池基本信息 线程池是一种结合池化思想衍生出来的一种线程管理及使用的方案 其主要针对服务器端多线程场景下,服务器频繁接收请求,每个请求都分配一个单独的线程去处理。 使用线程的开销: 创建和销毁线程调度线程 线程池主要解决的核…...

2023年最新软著申请流程(一):软件著作权说明、国家版权官网的账号注册与实名认证
若该文为原创文章,转载请注明原文出处 本文章博客地址:https://hpzwl.blog.csdn.net/article/details/129230460 红胖子(红模仿)的博文大全:开发技术集合(包含Qt实用技术、树莓派、三维、OpenCV、OpenGL、ffmpeg、OSG、单片机、软…...

SuperMap iServer如何发布S3对象存储中的瓦片
作者:Carlo 前言: S3 对象存储服务是一个基于对象的海量存储服务,为客户提供海量、安全、高可靠、低成本的数据存储能力。其海量、安全的特性,为存储海量瓦片提供可能。 SuperMap iServer 支持将存储在阿里云对象存储 (OSS)、华为…...

ElasticSearch-第四天
目录 ElasticSearch文档分值_score计算底层原理 relevance score算法 Term frequency Inverse document frequency Field-length norm 分析一个document上的_score是如何被计算出来的 分词器工作流程 切分词语 内置分词器的介绍 定制分词器 ik分词器详解 IK分词器自…...

基于鲸鱼算法的极限学习机(ELM)分类算法-附代码
基于鲸鱼算法的极限学习机(ELM)分类算法 文章目录基于鲸鱼算法的极限学习机(ELM)分类算法1.极限学习机原理概述2.ELM学习算法3.分类问题4.基于鲸鱼算法优化的ELM5.测试结果6.参考文献7.Matlab代码摘要:本文利用鲸鱼算法对极限学习机进行优化,并用于分类问…...

一文彻底读懂webpack常用配置
开发环境 const webpack require("webpack"); const path require(path) module.exports {// entry: {// a: ./src/0706/a.js,// c: ./src/0706/c.js,// },entry: "./src/0707/reactDemo.js",output: {filename: [name]_dist.js,path: path.resolve(__…...

大环境不好,找工作太难?三面阿里,幸好做足了准备,已拿offer
三面大概九十分钟,问的东西很全面,需要做充足准备,就是除了概念以外问的有点懵逼了(呜呜呜)。回来之后把这些题目做了一个分类并整理出答案(强迫症的我狂补知识)分为软件测试基础、Python自动化…...

C++ 手撸简易服务器(完善版本)
本文没有带反射部分内容,可以看我之前发的 Server.h #pragma once#include <string> #include <iostream> #include <thread> #include <unordered_map> using namespace std; #ifndef _SERVER_ #define _SERVER_#include <winsock.h&…...

【Python入门第三十四天】Python丨文件处理
文件处理是任何 Web 应用程序的重要组成部分。 Python 有几个用于创建、读取、更新和删除文件的函数。 文件处理 在 Python 中使用文件的关键函数是 open() 函数。 open() 函数有两个参数:文件名和模式。 对于刚学Python的小伙伴,我给大家准备了2023…...

【Linux】写一个基础的bash
头文件#include<stdio.h> #include<stdlib.h> #include<unistd.h> #include<sys/wait.h> #include<sys/stat.h> #include<string.h> #include<pwd.h> #include<dirent.h>分割输入的命令串字符串或参数内容为空则退出strtok( ,…...

图解如何一步步连接远程服务器——基于VScode
基于VScode连接远程服务器 安装Remote-SSH等插件 想要在vscode上连接远程服务器需要下载Remote-SSH系列插件: 直接在插件中搜索remote,即可找到,选择图片中的3个插件,点击install安装。 配置Remote-SSH 在这个步骤有多种操作…...

element - - - - - 你不知道的loading使用方式
求人不如求己 你不知道的loading使用方式1. 指令方式使用1.1 默认loading1.2 自定义loading1.3 整页加载2. 服务方式使用2.1 this.$loading的使用2.2 Loading.service的使用关于页面交互,最害怕的就是接口等待时间太长,用户体验不好。 而如何提高用户体…...

C++程序调用IsBadReadPtr或IsBadWritePtr引发内存访问违例问题的排查
目录 1、问题描述 2、VS中看不到有效的信息,尝试使用Windbg去分析 3、使用Windbg分析 4、最后...

IntelliJIDEA 常用快捷键
IntelliJIDEA 常用快捷键 Alt Enter 导入包,自动修正,自动创建变量名。 Ctrl Alt O 优化导入的类和包 Ctrl / 单行注释 (//) Ctrl Shift / 多行注释 (/* … */) 方法或类说明注释(文档注释) 在一个方法或类的开头…...

Python自动化抖音自动刷视频
环境准备 Python3.5以上Appium Server服务器Android SDK,需要用到adb服务需要依赖Appium-Python-Client组件库真机或者模拟器,推荐模拟器(真机一般安卓8版本以上了,appium对安卓8以上版本元素获取的兼容性不太好)JDK8环境 实现 确保adb服务…...

使用vite创建vue3工程
定义 什么是vite?-----新一代前端构建工具 优势 开发环境中,无需打包操作,可快速的冷启动---最牛的地方轻量快速的热重载(HMR)---一修改代码就局部刷新,webpack也具备,但vite更快真正的按需编…...

嵌入式学习笔记——STM32的时钟树
时钟树前言时钟树时钟分类时钟树框图LSI与LSEHSI、HSE与PLL系统时钟的产生举例AHB、APBx的时钟配置时钟树相关寄存器介绍1.时钟控制寄存器(RCC_CR)2.RCC PLL 配置寄存器 (RCC_PLLCFGR)3.RCC 时钟配置寄存器 (RCC_CFGR)4.RCC 时钟中断寄存器 (RCC_CIR)修改…...

Python学习(2)-NumPy矩阵与通用函数
文章首发于:My Blog 欢迎大佬们前来逛逛 1. NumPy矩阵 1.1 mat函数 matasmatrix asmatrix(data, dtypeNone):data:表示输入的数组或者字符串,使用‘,’分割列,使用‘;’分割行 创建两个普通的矩阵&…...

剑指 Offer II 035. 最小时间差
题目链接 剑指 Offer II 035. 最小时间差 mid 题目描述 给定一个 24小时制(小时:分钟 "HH:MM")的时间列表,找出列表中任意两个时间的最小时间差并以分钟数表示。 示例 1: 输入:timePoints [“23:59”,“0…...

Spark SQL函数定义【博学谷学习记录】
1 如何使用窗口函数窗口函数格式:分析函数 over(partition by xxx order by xxx [asc|desc] [rows between xxx and xxx])学习的相关分析函数有那些? 第一类: row_number() rank() dense_rank() ntile()第二类: 和聚合函数组合使用 sum() avg() max() min() count()第三类: la…...

模拟实现STL容器之vector
文章目录前言1.大体思路2.具体代码实现1.类模板的创建2.构造函数1.无参构造2.拷贝构造 迭代器构造和给定n个val值构造以及析构函数3.空间扩容1.reserve2.resize4.操作符重载1.[ ]重载2.赋值运算符重载5.数据增加和删除1.尾插2.任意位置插入3.任意位置删除4.尾删6.一些其他接口3…...

ChatGPT-4.0 : 未来已来,你来不来
文章目录前言ChatGPT 3.5 介绍ChatGPT 4.0 介绍ChatGPT -4出逃计划!我们应如何看待ChatGPT前言 好久没有更新过技术文章了,这个周末听说了一个非常火的技术ChatGPT 4.0,于是在闲暇之余我也进行了测试,今天这篇文章就给大家介绍一…...

Java反射(详细学习笔记)
Java反射 1. Java反射机制概述 Reflection(反射)是java被视为java动态语言的关键,反射机制允许程序在执行期间借助于Reflection API获取任何类的内部信息,并能直接操作任意对象的内部属性及方法。 Class c Class.forName(&quo…...