开源cJson用法
cJSON
cJSON是一个使用C语言编写的JSON数据解析器,具有超轻便,可移植,单文件的特点,使用MIT开源协议。
cJSON项目托管在Github上,仓库地址如下:
https://github.com/DaveGamble/cJSON
使用Git命令将其拉取到本地:
git clone https://github.com/DaveGamble/cJSON.git
1
从Github拉取cJSON源码后,文件非常多,但是其中cJSON的源码文件只有两个:
cJSON.h
cJSON.c
使用的时候,只需要将这两个文件复制到工程目录,然后包含头文件cJSON.h即可,如下:
#include "cJSON.h"
1
2. cJSON数据结构和设计思想
cJSON的设计思想从其数据结构上就能反映出来。
cJSON使用cJSON结构体来表示一个JSON数据,定义在cJSON.h中,源码如下:
/* 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的设计很巧妙。
首先,它不是将一整段JSON数据抽象出来,而是将其中的一条JSON数据抽象出来,也就是一个键值对,用上面的结构体 strcut cJSON 来表示,其中用来存放值的成员列表如下:
String:用于表示该键值对的名称;
type:用于表示该键值对中值的类型;
valuestring:如果键值类型(type)是字符串,则将该指针指向键值;
valueint:如果键值类型(type)是整数,则将该指针指向键值;
valuedouble:如果键值类型(type)是浮点数,则将该指针指向键值;
其次,一段完整的JSON数据中由很多键值对组成,并且涉及到键值对的查找、删除、添加,所以使用链表来存储整段JSON数据,如上面的代码所示:
next指针:指向下一个键值对
prev指针指向上一个键值对
最后,因为JSON数据支持嵌套,所以一个键值对的值会是一个新的JSON数据对象(一条新的链表),也有可能是一个数组,方便起见,在cJSON中,数组也表示为一个数组对象,用链表存储,所以:
在键值对结构体中,当该键值对的值是一个嵌套的JSON数据或者一个数组时,由child指针指向该条新链表。
3. JSON数据封装
封装方法
封装JSON数据的过程,其实就是创建链表和向链表中添加节点的过程。
首先来讲述一下链表中的一些术语:
头指针:指向链表头结点的指针;
头结点:不存放有效数据,方便链表操作;
首节点:第一个存放有效数据的节点;
尾节点:最后一个存放有效数据的节点;
明白了这几个概念之后,我们开始讲述创建一段完整的JSON数据,即如何创建一条完整的链表。
① 创建头指针:
cJSON* cjson_test = NULL;
1
② 创建头结点,并将头指针指向头结点:
cjson_test = cJSON_CreateObject();
1
③ 尽情的向链表中添加节点:
cJSON_AddNullToObject(cJSON * const object, const char * const name);
cJSON_AddTrueToObject(cJSON * const object, const char * const name);
cJSON_AddFalseToObject(cJSON * const object, const char * const name);
cJSON_AddBoolToObject(cJSON * const object, const char * const name, const cJSON_bool boolean);
cJSON_AddNumberToObject(cJSON * const object, const char * const name, const double number);
cJSON_AddStringToObject(cJSON * const object, const char * const name, const char * const string);
cJSON_AddRawToObject(cJSON * const object, const char * const name, const char * const raw);
cJSON_AddObjectToObject(cJSON * const object, const char * const name);
cJSON_AddArrayToObject(cJSON * const object, const char * const name);
输出JSON数据
上面讲述,一段完整的JSON数据就是一条长长的链表,那么,如何打印出这段JSON数据呢?
cJSON提供了一个API,可以将整条链表中存放的JSON信息输出到一个字符串中:
(char *) cJSON_Print(const cJSON *item);
1
使用的时候,只需要接收该函数返回的指针地址即可。
封装数据和打印数据示例
单纯的讲述方法还不够,下面用一个例子来说明,封装出开头给出的那段JSON数据:
#include <stdio.h>
#include "cJSON.h"
int main(void)
{
cJSON* cjson_test = NULL;
cJSON* cjson_address = NULL;
cJSON* cjson_skill = NULL;
char* str = NULL;
/* 创建一个JSON数据对象(链表头结点) */
cjson_test = cJSON_CreateObject();
/* 添加一条字符串类型的JSON数据(添加一个链表节点) */
cJSON_AddStringToObject(cjson_test, "name", "mculover666");
/* 添加一条整数类型的JSON数据(添加一个链表节点) */
cJSON_AddNumberToObject(cjson_test, "age", 22);
/* 添加一条浮点类型的JSON数据(添加一个链表节点) */
cJSON_AddNumberToObject(cjson_test, "weight", 55.5);
/* 添加一个嵌套的JSON数据(添加一个链表节点) */
cjson_address = cJSON_CreateObject();
cJSON_AddStringToObject(cjson_address, "country", "China");
cJSON_AddNumberToObject(cjson_address, "zip-code", 111111);
cJSON_AddItemToObject(cjson_test, "address", cjson_address);
/* 添加一个数组类型的JSON数据(添加一个链表节点) */
cjson_skill = cJSON_CreateArray();
cJSON_AddItemToArray(cjson_skill, cJSON_CreateString( "C" ));
cJSON_AddItemToArray(cjson_skill, cJSON_CreateString( "Java" ));
cJSON_AddItemToArray(cjson_skill, cJSON_CreateString( "Python" ));
cJSON_AddItemToObject(cjson_test, "skill", cjson_skill);
/* 添加一个值为 False 的布尔类型的JSON数据(添加一个链表节点) */
cJSON_AddFalseToObject(cjson_test, "student");
/* 打印JSON对象(整条链表)的所有数据 */
str = cJSON_Print(cjson_test);
printf("%s\n", str);
return 0;
}
编译运行:
gcc cJSON.c example1.c -o example1.exe
相关文章:
开源cJson用法
cJSON cJSON是一个使用C语言编写的JSON数据解析器,具有超轻便,可移植,单文件的特点,使用MIT开源协议。 cJSON项目托管在Github上,仓库地址如下: https://github.com/DaveGamble/cJSON 使用Git命令将其拉…...
【学习笔记】理解深度学习和机器学习的数学基础:数值计算
深度学习作为人工智能领域的一个重要分支,其算法的实现和优化离不开数值计算。数值计算在深度学习中扮演着至关重要的角色,它涉及到如何在计算机上高效、准确地解决数学问题。本文将介绍深度学习中数值计算的一些关键概念和挑战,以及如何应对…...

如何使用CSS让页面文本两行显示,超出省略号表示
talk is cheap, show me the code 举个栗子,如下: <span class"a">我说说<b class"b">打瞌睡党风建设打火机</b>说说色儿</span>a{display:block/inline-block;width:100px;overflow: hidden; white-spac…...

likeshop同城跑腿系统likeshop回收租赁系统likeshop多商户商城安装及小程序对接方法
前言:首先likeshop是一个开发平台,是一个独创的平台就像TP内核平台一样,你可以在这个平台上开发和衍生出很多伟大的产品,以likeshop为例,他们开发出商城系统,团购系统,外卖点餐系统,…...
C# 与 Windows API 交互的“秘密武器”:结构体和联合体
一、引言 在 C# 的编程世界里,当我们想要深入挖掘 Windows 系统的底层功能,与 Windows API 打交道时,结构体和联合体就像是两把神奇的钥匙🔑 它们能够帮助我们精准地操控数据,实现一些高级且强大的功能。就好比搭建一…...
PHP 使用 Redis
PHP 使用 Redis PHP 是一种广泛使用的服务器端编程语言,而 Redis 是一个高性能的键值对存储系统。将 PHP 与 Redis 结合使用,可以为 Web 应用程序提供快速的读写性能和丰富的数据结构。本文将详细介绍如何在 PHP 中使用 Redis,包括安装、连接、基本操作以及一些高级应用。 …...
嵌入式系统Linux实时化(四)Xenomai应用开发测试
1、Xenomai 原生API 任务管理 Xenomai 本身提供的一系列多任务调度机制,主要有以下一些函数: int rt_task_create (RT_TASK task, const char name, int stksize, int prio, intmode) ; 任务的创建;int rt_task_start(RT_TASK task, void(entry)(void cookie), void cookie…...

26个开源Agent开发框架调研总结(2)
根据Markets & Markets的预测,到2030年,AI Agent的市场规模将从2024年的50亿美元激增至470亿美元,年均复合增长率为44.8%。 Gartner预计到2028年,至少15%的日常工作决策将由AI Agent自主完成,AI Agent在企业应用中…...
Element UI与Element Plus:深度剖析
文章目录 前言一、概述二、技术特性三、设计理念四、使用体验五、迁移指南结语 前言 随着前端开发技术的快速发展,Vue.js 生态系统中的组件库也在不断进化。Element UI 和 Element Plus 是两个深受开发者喜爱的 Vue 组件库,它们分别构建于 Vue 2.x 和 V…...

二、BIO、NIO编程与直接内存、零拷贝
一、网络通信 1、什么是socket? Socket 是应用层与 TCP/IP 协议族通信的中间软件抽象层,它是一组接口,一般由操作 系统提供。客户端连接上一个服务端,就会在客户端中产生一个 socket 接口实例,服务端每接受 一个客户端…...
VSCode 更好用的设置
配置 {"terminal.integrated.fontSize": 15,"security.workspace.trust.untrustedFiles": "open","editor.minimap.enabled": false,"workbench.colorTheme": "Visual Studio 2017 Light - C","gnuGlobal.c…...

【git】-3 github创建远程仓库,上传自己的项目,下载别人的项目
一、如何使用Github 1、创建远程仓库 2、使用github拉取/推送代码 克隆仓库 向远程仓库推送代码-git push 二、上传我们自己的项目到github 方法一:直接上传 方法二:使用git命令 方法三: 将仓库拉取到本地上传 三、下载别人的项目 …...

计算机组成原理(1)
系统概述 计算机硬件基本组成早期冯诺依曼机现代计算机 计算机各部分工作原理主存储器运算器控制器计算机工作过程 此文章的图片资源获取来自于王道考研 计算机硬件基本组成 早期冯诺依曼机 存储程序是指将指令以二进制的形式事先输入到计算机的主存储器,然后按照…...

Openstack网络组件之Neutron
从Nova到Neutron:OpenStack网络架构的演变 在云计算和虚拟化技术迅猛发展的背景下,OpenStack 成为了构建私有云和公有云平台的首选解决方案之一。早期版本中,Nova 项目不仅负责计算资源的管理,还承担了提供基本网络连接的任务。然…...
神州数码交换机和路由器命令总结
神州数码交换机和路由器命令总结 一、神州数码交换机命令总结 1. 交换机恢复出厂设置及其基本配置. 1) //进入特权模式 2) del startup.cfg 2. Telnet方式管理交换机. 1) //进入全局配置模式 2) enable password 0 [密码] 3) Line 0 4 4) Password 0 [密码] 5) Login 3. 交换机…...

Spring MVC简单数据绑定
【图书介绍】《SpringSpring MVCMyBatis从零开始学(视频教学版)(第3版)》_springspringmvcmybatis从零开始 代码、课件、教学视频与相关软件包下载-CSDN博客 《SpringSpring MVCMyBatis从零开始学(视频教学版)(第3版&…...
《SQL ORDER BY》
《SQL ORDER BY》 介绍 SQL(Structured Query Language)是一种用于管理关系数据库管理系统的标准编程语言。ORDER BY语句是SQL中的一个重要部分,它用于对查询结果进行排序。在本篇文章中,我们将详细介绍SQL ORDER BY语句的用法、语法、示例以及一些高级应用。 语法 ORD…...

RabbitMQ基础(简单易懂)
RabbitMQ高级篇请看: RabbitMQ高级篇-CSDN博客 目录 什么是RabbitMQ? MQ 的核心概念 1. RabbitMQ 的核心组件 2. Exchange 的类型 3. 数据流向说明 如何安装RabbitQueue? WorkQueue(工作队列): Fa…...
DNS解析域名简记
域名通常是由: 权威域名.顶级域名.根域名组成的。 从左往右,级别依次升高,这和外国人从小范围到大范围的说话习惯相关。(我们自己是更习惯先说大范围再说小范围,如XX省XX市XX区XX路) DNS解析域名时,会先查…...

【2024年华为OD机试】(B卷,100分)- 求最小步数 (Java JS PythonC/C++)
一、问题描述 题目描述 求从坐标零点到坐标点 n 的最小步数,一次只能沿横坐标轴向左或向右移动 2 或 3。 注意:途径的坐标点可以为负数。 输入描述 坐标点 n 输出描述 输出从坐标零点移动到坐标点 n 的最小步数。 备注 1 < n < 10^9 用例…...
【网络】每天掌握一个Linux命令 - iftop
在Linux系统中,iftop是网络管理的得力助手,能实时监控网络流量、连接情况等,帮助排查网络异常。接下来从多方面详细介绍它。 目录 【网络】每天掌握一个Linux命令 - iftop工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景…...
内存分配函数malloc kmalloc vmalloc
内存分配函数malloc kmalloc vmalloc malloc实现步骤: 1)请求大小调整:首先,malloc 需要调整用户请求的大小,以适应内部数据结构(例如,可能需要存储额外的元数据)。通常,这包括对齐调整,确保分配的内存地址满足特定硬件要求(如对齐到8字节或16字节边界)。 2)空闲…...
【根据当天日期输出明天的日期(需对闰年做判定)。】2022-5-15
缘由根据当天日期输出明天的日期(需对闰年做判定)。日期类型结构体如下: struct data{ int year; int month; int day;};-编程语言-CSDN问答 struct mdata{ int year; int month; int day; }mdata; int 天数(int year, int month) {switch (month){case 1: case 3:…...

RocketMQ延迟消息机制
两种延迟消息 RocketMQ中提供了两种延迟消息机制 指定固定的延迟级别 通过在Message中设定一个MessageDelayLevel参数,对应18个预设的延迟级别指定时间点的延迟级别 通过在Message中设定一个DeliverTimeMS指定一个Long类型表示的具体时间点。到了时间点后…...

Spark 之 入门讲解详细版(1)
1、简介 1.1 Spark简介 Spark是加州大学伯克利分校AMP实验室(Algorithms, Machines, and People Lab)开发通用内存并行计算框架。Spark在2013年6月进入Apache成为孵化项目,8个月后成为Apache顶级项目,速度之快足见过人之处&…...

基于uniapp+WebSocket实现聊天对话、消息监听、消息推送、聊天室等功能,多端兼容
基于 UniApp + WebSocket实现多端兼容的实时通讯系统,涵盖WebSocket连接建立、消息收发机制、多端兼容性配置、消息实时监听等功能,适配微信小程序、H5、Android、iOS等终端 目录 技术选型分析WebSocket协议优势UniApp跨平台特性WebSocket 基础实现连接管理消息收发连接…...

YSYX学习记录(八)
C语言,练习0: 先创建一个文件夹,我用的是物理机: 安装build-essential 练习1: 我注释掉了 #include <stdio.h> 出现下面错误 在你的文本编辑器中打开ex1文件,随机修改或删除一部分,之后…...

智能在线客服平台:数字化时代企业连接用户的 AI 中枢
随着互联网技术的飞速发展,消费者期望能够随时随地与企业进行交流。在线客服平台作为连接企业与客户的重要桥梁,不仅优化了客户体验,还提升了企业的服务效率和市场竞争力。本文将探讨在线客服平台的重要性、技术进展、实际应用,并…...

项目部署到Linux上时遇到的错误(Redis,MySQL,无法正确连接,地址占用问题)
Redis无法正确连接 在运行jar包时出现了这样的错误 查询得知问题核心在于Redis连接失败,具体原因是客户端发送了密码认证请求,但Redis服务器未设置密码 1.为Redis设置密码(匹配客户端配置) 步骤: 1).修…...

让回归模型不再被异常值“带跑偏“,MSE和Cauchy损失函数在噪声数据环境下的实战对比
在机器学习的回归分析中,损失函数的选择对模型性能具有决定性影响。均方误差(MSE)作为经典的损失函数,在处理干净数据时表现优异,但在面对包含异常值的噪声数据时,其对大误差的二次惩罚机制往往导致模型参数…...