【C语言之 CJson】学CJson看这一篇就够了
文章目录
- 前言
- 一、下载CJson
- 二、创建一个json
- 2.1 创建json对象
- cJSON类型详解
- 2.2 创建键值对
- 2.3 添加嵌套的 JSON 对象
- 2.4 添加数组
- 创建数组
- 添加元素到数组
- 添加数组到obj
- 2.5 将 JSON 对象转为字符串
- 2.6 释放内存
- 2.7 示例代码
- 三、解析json
- 3.1 解析json root
- 3.2 把一个key解析出来变成cJSON对象
- 3.3 判断cJSON的存储的类型
- 3.4 获取键值对的值
- 3.5 获取和遍历数组
- 获取数组里面指定index的值
- 获取数组的大小
- 遍历数组
- 总结
前言
CJSON 是一个轻量级的、用于处理 JSON 数据的 C 语言库。它提供了简单而直观的 API,使得在 C 程序中处理 JSON 数据变得相对容易。在本文中,我们将介绍 CJSON 的基本使用,包括如何创建 JSON 对象、解析 JSON 字符串、访问 JSON 数据以及释放相关资源。
一、下载CJson
打开这个链接:CJson下载
可以使用上面这两种下载方式。
点击去下载好的文件后,我们只需要其中的cJSON.c和cJSON.h文件即可。
只需要在我们main里面包含cJSON.h即可
二、创建一个json
2.1 创建json对象
在我们的json中,他的结构如下:
{...
}
外面的大括号就是我们的root,我们就先创建他才能进行后续的操作
函数原型:
CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void);
无参数,返回值为cJSON 的指针
cJSON类型详解
cJson结构体如下定义:
/* The cJSON structure: */
typedef struct cJSON
{/* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */struct cJSON *next;struct cJSON *prev;/* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */struct cJSON *child;/* The type of the item, as above. */int type;/* The item's string, if type==cJSON_String and type == cJSON_Raw */char *valuestring;/* writing to valueint is DEPRECATED, use cJSON_SetNumberValue instead */int valueint;/* The item's number, if type==cJSON_Number */double valuedouble;/* The item's name string, if this item is the child of, or is in the list of subitems of an object. */char *string;
} cJSON;
这是 cJSON 库中定义的结构体 cJSON,它用于表示 JSON 数据的各个部分。以下是各个成员的解释:
next/prev:
struct cJSON *next;
struct cJSON *prev;
这两个成员用于在数组或对象中遍历链表。你可以通过这两个指针在链表中移动,或者使用 cJSON 库提供的函数 GetArraySize、GetArrayItem、GetObjectItem 来进行相应的操作。
child:
struct cJSON *child;
如果当前项是一个数组或对象,child 指向一个链表,表示数组或对象中的各个元素。通过这个链表,你可以访问数组的各个元素或对象的各个成员。
type:
int type;
表示当前项的类型,可以是以下几种之一:
cJSON_False
cJSON_True
cJSON_NULL
cJSON_Number
cJSON_String
cJSON_Array
cJSON_Object
cJSON_Raw
valuestring:
char *valuestring;
如果当前项的类型是 cJSON_String 或 cJSON_Raw,valuestring 指向存储字符串值的字符数组。
valueint:
int valueint;
DEPRECATED:以前用于存储整数值,现在推荐使用 cJSON_SetNumberValue 函数设置数字值。
valuedouble:
double valuedouble;
如果当前项的类型是 cJSON_Number,valuedouble 存储该项的数字值。
string:
char *string;
如果当前项是一个对象的成员,string 存储该成员的名称(键)。如果当前项是一个数组的元素,string 可能为 NULL。
这些成员组合在一起,使得 cJSON 结构体能够表示 JSON 数据的结构和内容。通过递归访问 next、prev、child 指针,可以遍历整个 JSON 数据。
2.2 创建键值对
使用下面这个函数即可创建一个键值对
CJSON_PUBLIC(cJSON*) cJSON_AddStringToObject(cJSON * const object, const char * const name, const char * const string)
这个函数是 cJSON 库中的一个函数,用于向一个 JSON 对象(或者说 JSON 字典)中添加一个字符串类型的键值对。
返回值:
cJSON*:这个函数返回一个指向新添加的 JSON 元素的指针。这个元素包含了添加的字符串值。如果添加失败,返回 NULL。
参数:
cJSON * const object:
这是一个指向 JSON 对象的指针,表示你要往哪个对象中添加键值对。
const char * const name:
这是一个字符串,表示你要添加的键的名称(key)。
const char * const string:
这是一个字符串,表示你要添加的值。这个值是一个字符串类型的 JSON 元素。
所以,这个函数的作用就是往一个 JSON 对象中添加一个键值对,键是 name,值是 string,然后返回一个指向新添加元素的指针。如果添加失败,返回 NULL。
2.3 添加嵌套的 JSON 对象
使用下面这个函数为添加嵌套的json对象
CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item)
返回值:
cJSON_bool:这是一个表示成功或失败的布尔值。如果成功添加元素,返回 true,否则返回 false。
参数:
cJSON *object:
这是一个指向 JSON 对象的指针,表示你要往哪个对象中添加元素。
const char *string:
这是一个字符串,表示你要添加的键的名称(key)。
cJSON *item:
这是一个指向要添加的 JSON 元素的指针。可以是任何 JSON 数据类型,比如字符串、数字、数组等。
所以,这个函数的作用就是往一个 JSON 对象中添加一个键值对,键是 string,值是 item,然后返回一个布尔值,表示添加是否成功。如果成功,返回 true,否则返回 false。
2.4 添加数组
创建数组
CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void);
无参数,返回值为cJSON,这个数组的指针
添加元素到数组
CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToArray(cJSON *array, cJSON *item);
返回值:
cJSON_bool:这是一个表示成功或失败的布尔值。如果成功添加元素,返回 true,否则返回 false。
参数:
CJSON *array:
这是一个指向 JSON 数组的指针,表示你要往哪个数组中添加元素。
CJSON *item:
这是一个指向要添加的 JSON 元素的指针。可以是任何 JSON 数据类型,比如字符串、数字、对象等。
所以,这个函数的作用就是往一个 JSON 数组中添加一个元素,元素的内容由 item 指定,然后返回一个布尔值,表示添加是否成功。如果成功,返回 true,否则返回 false。
添加数组到obj
CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item)
这个函数是 cJSON 库中的一个函数,用于向一个 JSON 对象(或者说 JSON 字典)中添加一个 JSON 元素。
返回值:
cJSON_bool:这是一个表示成功或失败的布尔值。如果成功添加元素,返回 true,否则返回 false。
参数:
cJSON *object:
这是一个指向 JSON 对象的指针,表示你要往哪个对象中添加元素。
const char *string:
这是一个字符串,表示你要添加的键的名称(key)。
cJSON *item:
这是一个指向要添加的 JSON 元素的指针。可以是任何 JSON 数据类型,比如字符串、数字、数组、对象等。
所以,这个函数的作用就是往一个 JSON 对象中添加一个键值对,键是 string,值是 item,然后返回一个布尔值,表示添加是否成功。如果成功,返回 true,否则返回 false。
2.5 将 JSON 对象转为字符串
使用下面这个函数就可以把你的json转换成字符串了
CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item);
返回值:
char *:这是一个指向字符数组的指针,表示包含 JSON 元素内容的字符串。需要注意的是,这个返回的字符串是在堆上动态分配的,所以在使用完毕后,需要负责释放内存以防止内存泄漏。
参数:
const cJSON *item:
这是一个指向 cJSON 元素的指针,表示你要将哪个 JSON 元素转换成字符串。
所以,这个函数的作用就是把一个 cJSON 元素转换成字符串,并返回这个字符串的指针。你可以通过这个返回的字符串来获取 JSON 元素的文本表示。
如果填root则是把整个json变成字符串
2.6 释放内存
使用下面这个函数即可释放我们的内存
CJSON_PUBLIC(void) cJSON_Delete(cJSON *item)
参数一般填我们的root
2.7 示例代码
#include <stdio.h>
#include <stdlib.h>
#include "cJSON.h"char Json[1024] = { '\0' };void ReadJson()
{FILE* f = NULL;fopen_s(&f, "learn.json", "r");fread(Json, 1, 1023, f);printf("%s\n", Json);fclose(f);
}int main() {// 创建 JSON 对象cJSON* root = cJSON_CreateObject();// 添加基本键值对cJSON_AddStringToObject(root, "name", "John");cJSON_AddNumberToObject(root, "age", 30);// 添加嵌套的 JSON 对象(地址)cJSON* address = cJSON_CreateObject();cJSON_AddStringToObject(address, "street", "123 Main St");cJSON_AddStringToObject(address, "city", "Anytown");cJSON_AddStringToObject(address, "postalCode", "12345");cJSON_AddItemToObject(root, "address", address);// 添加数组cJSON* interests = cJSON_CreateArray();cJSON_AddItemToArray(interests, cJSON_CreateString("Reading"));cJSON_AddItemToArray(interests, cJSON_CreateString("Gardening"));cJSON_AddItemToArray(interests, cJSON_CreateString("Cooking"));cJSON_AddItemToObject(root, "interests", interests);// 将 JSON 对象转为字符串char* jsonString = cJSON_Print(root);printf("JSON Object:\n%s\n", jsonString);// 释放内存cJSON_Delete(root);free(jsonString);return 0;
}
三、解析json
3.1 解析json root
使用下面这个函数,就可以把一个const char *的字符串解析成cJSON对象了
CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value);
检测是否解析成功:
if (root == NULL) {const char* error_ptr = cJSON_GetErrorPtr();if (error_ptr != NULL) {fprintf(stderr, "Error before: %s\n", error_ptr);}return 1; // Exit with an error code
}
3.2 把一个key解析出来变成cJSON对象
CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON * const object, const char * const string)
返回值:
cJSON *:这是一个指向 cJSON 元素的指针,表示获取到的值。如果指定键存在于 JSON 对象中,就返回对应的值;如果不存在,则返回 NULL。
参数:
const cJSON * const object:
这是一个指向 JSON 对象的指针,表示你要从哪个对象中获取值。
const char * const string:
这是一个字符串,表示你要获取的值对应的键的名称(key)。
所以,这个函数的作用就是在给定的 JSON 对象中查找指定键的值,如果找到了就返回对应的值的指针,如果找不到就返回 NULL。这个函数是区分大小写的,意味着键的名称要严格匹配,大小写一致。
3.3 判断cJSON的存储的类型
在CJSON中有这么一些函数,他的参数为cJson指针类型,用他们可以判断里面是什么类型的,以便后续的操作
/* These functions check the type of an item */
CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON * const item);
3.4 获取键值对的值
在CJSON中有这两个函数,他们的参数为cJSON指针对象,返回值为值
/* Check item type and return its value */
CJSON_PUBLIC(char *) cJSON_GetStringValue(const cJSON * const item);
CJSON_PUBLIC(double) cJSON_GetNumberValue(const cJSON * const item);
除了使用函数,我们也可以使用cJSON里面的成员进行或者值。
例如:
int age_value = age->valueint;
3.5 获取和遍历数组
获取数组里面指定index的值
使用下面这个函数即可获取指定index的cJson类型了
CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index);
获取数组的大小
使用下面这个函数就可以获取array里面有几个元素了
/* Returns the number of items in an array (or object). */
CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array);
遍历数组
cJSON* scores = cJSON_GetObjectItemCaseSensitive(root, "scores");
if (cJSON_IsArray(scores)) {int array_size = cJSON_GetArraySize(scores);printf("Scores: ");for (int i = 0; i < array_size; i++) {cJSON* score_element = cJSON_GetArrayItem(scores, i);if (cJSON_IsNumber(score_element)) {printf("%d ", score_element->valueint);}}printf("\n");
}
总结
CJSON 提供了一个简单而功能丰富的方式来处理 JSON 数据。通过创建 JSON 对象、数组,以及使用相应的函数来填充和访问数据,你可以在 C 语言中轻松地进行 JSON 操作。在使用 cJSON 时,记得及时释放分配的内存以避免内存泄漏。
这篇文章提供了一个基本的入门指南,希望能够帮助你开始使用 CJSON 在 C 语言中处理 JSON 数据。如果你有更复杂的需求,建议查看 cJSON 的文档和示例代码,以更深入地了解其功能和用法。
相关文章:

【C语言之 CJson】学CJson看这一篇就够了
文章目录 前言一、下载CJson二、创建一个json2.1 创建json对象cJSON类型详解 2.2 创建键值对2.3 添加嵌套的 JSON 对象2.4 添加数组创建数组添加元素到数组添加数组到obj 2.5 将 JSON 对象转为字符串2.6 释放内存2.7 示例代码 三、解析json3.1 解析json root3.2 把一个key解析出…...

使用Java语言实现字母之间的大小写转换
这个类的作用为实现字母之间的大小写转换,通过加减32来完成。 输入的代码 import java.util.Scanner; public class WordChangeDemo {public static void main(String[] args){try (Scanner in new Scanner(System.in)) {System.out.println("请输入您要进…...

Docker的数据持久化;Docker网络;Dockerfile编写
Docker的数据持久化;Docker网络;Dockerfile编写; 文章目录 Docker的数据持久化;Docker网络;Dockerfile编写;**Docker的数据持久化**1)将本地目录映射到容器里2)数据卷3)将…...

OpenHarmony亮相MTSC 2023 | 质量效率共进,赋能应用生态发展
11月25日,MTSC 2023第十二届中国互联网测试开发大会在深圳登喜路国际大酒店圆满举行。大会以“软件质量保障体系和测试研发技术交流”为主要目的,旨在为行业搭建一个深入探讨和交流的桥梁和平台。OpenAtom OpenHarmony(简称“OpenHarmony”&a…...

windows11 调整鼠标灵敏度方法
首先 我们打开电脑设置 或者在 此电脑/此计算机/我的电脑 右击选择属性 然后 有的电脑 左侧菜单中 直接就有 设备 然后在设备中直接就可以找到 鼠标 选项 调整光标速度即可 如果操作系统和我的一样 可以直接搜索鼠标 然后 选择 鼠标设置 然后 调整上面的鼠标指针速度即可...
贪心算法个人见解
目录 基本思想: 贪心算法的步骤: 示例: 贪心算法(Greedy Algorithm)是一种基于贪心策略的算法范式,它在每一步选择中都采取当前状态下的最优选择,而不考虑全局最优解。贪心算法通常适用于那些…...

Win中Redis部署与配置
1.下载msi版本 下载传送门 2.双击next-->next安装安装 3.密码配置以及开机自启 在配置文件中配置相应配置进行配置密码以及端口和ip port 6379指定 Redis 监听端口,默认端口为 6379,作者在自己的一篇博文中解释了为什么选用 6379 作为默认端口&…...
vue el-button 封装及使用
使用了 Element UI 中的 el-button 组件,并对其进行了封装和定制。 创建组件index.vue (src/common-ui/button/index.vue) <template><el-buttonclass"h-button":type"type":icon"hIcon":disabled"disabled"clic…...
QT之QMediaPlayer的用法
QT之QMediaPlayer的用法 成员函数例程 成员函数 1)setMedia(const QMediaContent &media, QIODevice *stream nullptr) 设置要播放的媒体内容,其中参数media指定了媒体内容,stream参数指定了用于读取媒体的输入设备(如文件流࿰…...

TCP_报文格式解读
报文格式 header部分字段含义解析 固定字段 对于header中固定部分字段含义,见之前的blog《TCP报文分析》; 对部分字段含义补充说明 Data Offset:4bit,tcp header的长度,单位:32bit(4字节&…...
C语言面试之旅:掌握基础,探索深度(面试实战之c语言关键词下篇)
一.枚举( enum) 枚举是 C 语言中的一种基本数据类型,用于定义一组具有离散值的常量,它可以让数据更简洁,更易读。枚举类型通常用于为程序中的一组相关的常量取名字,以便于程序的可读性和维护性。定义一个枚…...
Java学习第十三天
Java多态 多态是同一个行为具有多个不同表现形式或形态的能力。 多态就是同一个接口,使用不同的实例而执行不同操作 多态性是对象多种表现形式的体现。 多态的优点 1. 消除类型之间的耦合关系2. 可替换性3. 可扩充性4. 接口性5. 灵活性6. 简化性 多态存在的三个…...

【Delphi】实现彩色日志显示框(TRichEdit Helper)
目录 一、前言 二、实现方法 1. 第一步 2. 第二步 3. 第三步 三、主程序代码 四、下载 1. 可执行程序 2. 程序源代码 一、前言 在用Delphi做日常开发的时候,经常需要显示程序运行的日志,一般我们会使用TMemo,使用起来简单,…...

Elasticsearch 优化查询中获取字段内容的方式,性能提升5倍!
1、背景 集群配置为:8 个 node 节点,16 核 32G,索引 4 分片 1 副本。应用程序的查询逻辑是按经纬度排序后找前 200 条文档。 1、应用对查询要求比较高,search 没有慢查询的状态。 2、集群压测性能不能上去,cpu 使用未打…...

图像批量设计软件Retrobatch Pro mac中文版功能特色
Retrobatch Mac是一款灵活的批量图像处理工具。用户可以自由创建Workflow来实现相应的功能,这些Workflow能取代大量的重复劳动,提高生产力。Retrobatch Mac的一般操作是从左边栏拖动相应动作到工作区形成节点(Nodes),节…...
python第3天之函数
深入理解 Python 中的函数 简介 在编程中,函数是组织和复用代码的基本单元。Python 作为一门高级编程语言,提供了丰富的函数特性来帮助开发者编写清晰、模块化和高效的代码。在本文中,我们将深入探讨 Python 函数的定义、调用、参数、返回值…...

SQL Server 数据库,为products表添加数据
在插入数据的时候,需要注意以下事项。 > 每次插入一整行数据,不可能只插入半行或几列数据。 > 数据值的数目必须与列数相同,每个数据值的数据类型、精度和小数位数也必须与相应的 列匹配。 > INSERT语句不能为标识列指定值&#…...

C语言结构体详解(二)(能看懂文字就能明白系列)文章很长,慢慢品尝
系列文章目录 第一章 结构体的介绍和基本使用 🌟 个人主页:古德猫宁- 🌈 信念如阳光,照亮前行的每一步 文章目录 系列文章目录🌈 *信念如阳光,照亮前行的每一步* 前言前面一篇文章主要介绍了结构体的基础…...
WPF不使用AllowsTransparency实现高性能透明背景异形窗体
前言 最近在WPF项目中使用到异形窗体结合Webbroswer组件做web界面的公告展示,当时不想太麻烦引入Cef组件,就想用自带的Webbroswer来做展示,为了美观还做了异形窗体,结果测试就杯具了,自带的Webbroswer在AllowsTransparency=“True” 模式下根本就无法显示,界面一片空白,…...
唯创知音WT2605C语音芯片MP3音频IC:轻松实现指令随机播放与无缝循环播放等功能
在现代化的电子产品中,音频功能的重要性日益凸显。无论是智能家居、玩具、医疗设备还是仪器仪表,富有吸引力的音效与语音提示都能显著提升用户体验。唯创知音WT2605C语音芯片MP3音频IC便是为了满足这一需求而诞生的,它具备指令随机播放、无缝…...

Flask RESTful 示例
目录 1. 环境准备2. 安装依赖3. 修改main.py4. 运行应用5. API使用示例获取所有任务获取单个任务创建新任务更新任务删除任务 中文乱码问题: 下面创建一个简单的Flask RESTful API示例。首先,我们需要创建环境,安装必要的依赖,然后…...
C++:std::is_convertible
C++标志库中提供is_convertible,可以测试一种类型是否可以转换为另一只类型: template <class From, class To> struct is_convertible; 使用举例: #include <iostream> #include <string>using namespace std;struct A { }; struct B : A { };int main…...
基于数字孪生的水厂可视化平台建设:架构与实践
分享大纲: 1、数字孪生水厂可视化平台建设背景 2、数字孪生水厂可视化平台建设架构 3、数字孪生水厂可视化平台建设成效 近几年,数字孪生水厂的建设开展的如火如荼。作为提升水厂管理效率、优化资源的调度手段,基于数字孪生的水厂可视化平台的…...

从零开始打造 OpenSTLinux 6.6 Yocto 系统(基于STM32CubeMX)(九)
设备树移植 和uboot设备树修改的内容同步到kernel将设备树stm32mp157d-stm32mp157daa1-mx.dts复制到内核源码目录下 源码修改及编译 修改arch/arm/boot/dts/st/Makefile,新增设备树编译 stm32mp157f-ev1-m4-examples.dtb \stm32mp157d-stm32mp157daa1-mx.dtb修改…...
解决本地部署 SmolVLM2 大语言模型运行 flash-attn 报错
出现的问题 安装 flash-attn 会一直卡在 build 那一步或者运行报错 解决办法 是因为你安装的 flash-attn 版本没有对应上,所以报错,到 https://github.com/Dao-AILab/flash-attention/releases 下载对应版本,cu、torch、cp 的版本一定要对…...

select、poll、epoll 与 Reactor 模式
在高并发网络编程领域,高效处理大量连接和 I/O 事件是系统性能的关键。select、poll、epoll 作为 I/O 多路复用技术的代表,以及基于它们实现的 Reactor 模式,为开发者提供了强大的工具。本文将深入探讨这些技术的底层原理、优缺点。 一、I…...
安卓基础(aar)
重新设置java21的环境,临时设置 $env:JAVA_HOME "D:\Android Studio\jbr" 查看当前环境变量 JAVA_HOME 的值 echo $env:JAVA_HOME 构建ARR文件 ./gradlew :private-lib:assembleRelease 目录是这样的: MyApp/ ├── app/ …...
Spring AI Chat Memory 实战指南:Local 与 JDBC 存储集成
一个面向 Java 开发者的 Sring-Ai 示例工程项目,该项目是一个 Spring AI 快速入门的样例工程项目,旨在通过一些小的案例展示 Spring AI 框架的核心功能和使用方法。 项目采用模块化设计,每个模块都专注于特定的功能领域,便于学习和…...
vue3 daterange正则踩坑
<el-form-item label"空置时间" prop"vacantTime"> <el-date-picker v-model"form.vacantTime" type"daterange" start-placeholder"开始日期" end-placeholder"结束日期" clearable :editable"fal…...

解析两阶段提交与三阶段提交的核心差异及MySQL实现方案
引言 在分布式系统的事务处理中,如何保障跨节点数据操作的一致性始终是核心挑战。经典的两阶段提交协议(2PC)通过准备阶段与提交阶段的协调机制,以同步决策模式确保事务原子性。其改进版本三阶段提交协议(3PC…...