当前位置: 首页 > news >正文

C++ 中的 cJSON 解析库:用法、实现及递归解析算法与内存高效管理

在现代软件开发中,JSON(JavaScript Object Notation)作为一种轻量级的数据交换格式,因其易于阅读和编写、易于机器解析和生成的特性,被广泛应用于各种场景。C++ 作为一种强大的编程语言,自然也需要一个高效的 JSON 解析库来处理 JSON 数据。cJSON 是一个流行的 C/C++ JSON 解析库,它以其简洁的设计和高效的性能赢得了开发者的青睐。本文将详细介绍 cJSON 的用法、实现原理,特别是其递归解析算法和内存高效管理机制。

一、cJSON 简介

cJSON 是一个轻量级的 JSON 解析库,支持 C 和 C++ 语言。它提供了简单易用的 API,可以方便地解析 JSON 数据和生成 JSON 字符串。cJSON 的特点包括:

  • 轻量级:cJSON 的代码量较小,适合嵌入式系统和资源受限的环境。

  • 高性能:cJSON 使用高效的解析算法,能够快速解析和生成 JSON 数据。

  • 易用性:cJSON 提供了简洁的 API,开发者可以轻松上手。

  • 灵活性:cJSON 支持多种数据类型,包括对象、数组、字符串、数字、布尔值和 NULL。

二、cJSON 的安装与基本用法

1. 安装 cJSON

cJSON 是一个开源项目,可以在 GitHub 上获取其源代码。以下是安装步骤:

  1. 克隆仓库

    git clone https://github.com/DaveGamble/cJSON.git
  2. 编译

    cd cJSON
    make
  3. 安装

    sudo make install

2. 基本用法

以下是一个简单的示例,展示如何使用 cJSON 解析 JSON 数据:

#include <iostream>
#include "cJSON.h"int main() {const char *json_string = "{\"name\":\"John\",\"age\":30,\"city\":\"New York\"}";// 解析 JSON 字符串cJSON *json = cJSON_Parse(json_string);if (json == nullptr) {std::cerr << "Error parsing JSON data." << std::endl;return -1;}// 获取 JSON 对象中的值cJSON *name = cJSON_GetObjectItem(json, "name");cJSON *age = cJSON_GetObjectItem(json, "age");cJSON *city = cJSON_GetObjectItem(json, "city");if (cJSON_IsString(name)) {std::cout << "Name: " << name->valuestring << std::endl;}if (cJSON_IsNumber(age)) {std::cout << "Age: " << age->valueint << std::endl;}if (cJSON_IsString(city)) {std::cout << "City: " << city->valuestring << std::endl;}// 释放 JSON 对象cJSON_Delete(json);return 0;
}

3. 生成 JSON 数据

cJSON 也支持生成 JSON 数据,以下是一个示例:

#include <iostream>
#include "cJSON.h"int main() {// 创建 JSON 对象cJSON *json = cJSON_CreateObject();// 添加键值对cJSON_AddStringToObject(json, "name", "John");cJSON_AddNumberToObject(json, "age", 30);cJSON_AddStringToObject(json, "city", "New York");// 将 JSON 对象转换为字符串char *json_string = cJSON_Print(json);// 输出 JSON 字符串std::cout << json_string << std::endl;// 释放 JSON 对象和字符串cJSON_Delete(json);free(json_string);return 0;
}

三、cJSON 的递归解析算法

cJSON 的解析算法是递归的,这意味着它能够处理嵌套的 JSON 数据结构。递归解析算法的核心思想是将 JSON 数据分解为多个小的 JSON 对象,然后逐个解析这些对象。

1. 递归解析的基本原理

递归解析的基本原理是通过递归函数来处理 JSON 数据的嵌套结构。以下是一个简单的递归解析函数的示例:

void parse_json(cJSON *json) {if (json == nullptr) return;// 遍历 JSON 对象的每个子项cJSON *item = nullptr;cJSON_ArrayForEach(item, json) {if (cJSON_IsObject(item)) {std::cout << "Parsing object..." << std::endl;parse_json(item); // 递归解析嵌套对象} else if (cJSON_IsArray(item)) {std::cout << "Parsing array..." << std::endl;parse_json(item); // 递归解析嵌套数组} else if (cJSON_IsString(item)) {std::cout << "String: " << item->valuestring << std::endl;} else if (cJSON_IsNumber(item)) {std::cout << "Number: " << item->valueint << std::endl;} else if (cJSON_IsBool(item)) {std::cout << "Bool: " << (item->valueint ? "true" : "false") << std::endl;} else if (cJSON_IsNull(item)) {std::cout << "Null" << std::endl;}}
}

2. 递归解析的优势

递归解析算法的优势在于其简洁性和灵活性。它能够轻松处理嵌套的 JSON 数据结构,而不需要复杂的循环和条件判断。此外,递归解析算法的代码通常更加清晰和易于维护。

四、cJSON 的内存高效管理

cJSON 在内存管理方面采用了高效的设计,主要体现在以下几个方面:

1. 动态内存分配

cJSON 使用动态内存分配来存储解析后的 JSON 数据。这意味着它会根据实际需要分配内存,从而避免了内存浪费。以下是一个示例,展示如何使用动态内存分配:

cJSON *json = cJSON_CreateObject();
cJSON_AddStringToObject(json, "key", "value");
char *json_string = cJSON_Print(json);

在这个示例中,cJSON_CreateObjectcJSON_AddStringToObject 函数会动态分配内存来存储 JSON 对象和字符串。cJSON_Print 函数会将 JSON 对象转换为字符串,并动态分配内存来存储该字符串。

2. 内存释放

为了防止内存泄漏,cJSON 提供了 cJSON_Deletefree 函数来释放动态分配的内存。以下是一个示例:

cJSON_Delete(json);
free(json_string);

在这个示例中,cJSON_Delete 函数会释放 JSON 对象占用的内存,而 free 函数会释放 JSON 字符串占用的内存。

3. 内存管理的优势

cJSON 的内存管理设计具有以下优势:

  • 高效性:动态内存分配和释放能够提高内存使用效率,避免内存浪费。

  • 安全性:通过使用 cJSON_Deletefree 函数,可以防止内存泄漏,提高程序的稳定性。

  • 灵活性:动态内存分配和释放使得 cJSON 能够适应各种内存环境,包括嵌入式系统和资源受限的环境。

五、总结

cJSON 是一个功能强大且易于使用的 JSON 解析库,其递归解析算法和内存高效管理机制使其在处理 JSON 数据时表现出色。通过本文的介绍,希望读者能够对 cJSON 的用法、实现原理以及递归解析算法和内存高效管理有更深入的了解。在实际开发中,合理使用 cJSON 可以大大提高开发效率和程序性能。

相关文章:

C++ 中的 cJSON 解析库:用法、实现及递归解析算法与内存高效管理

在现代软件开发中&#xff0c;JSON&#xff08;JavaScript Object Notation&#xff09;作为一种轻量级的数据交换格式&#xff0c;因其易于阅读和编写、易于机器解析和生成的特性&#xff0c;被广泛应用于各种场景。C 作为一种强大的编程语言&#xff0c;自然也需要一个高效的…...

websocket自动重连封装

websocket自动重连封装 前端代码封装 import { ref, onUnmounted } from vue;interface WebSocketOptions {url: string;protocols?: string | string[];reconnectTimeout?: number; }class WebSocketService {private ws: WebSocket | null null;private callbacks: { [k…...

【C语言】球球大作战游戏

目录 1. 前期准备 2. 玩家操作 3. 生成地图 4. 敌人移动 5. 吃掉小球 6. 完整代码 1. 前期准备 游戏设定:小球的位置、小球的半径、以及小球的颜色 这里我们可以用一个结构体数组来存放这些要素,以方便初始化小球的信息。 struct Ball {int x;int y;float r;DWORD c…...

人工智能D* Lite 算法-动态障碍物处理、多步预测和启发式函数优化

在智能驾驶领域&#xff0c;D* Lite 算法是一种高效的动态路径规划算法&#xff0c;适用于处理环境变化时的路径重规划问题。以下将为你展示 D* Lite 算法的高级用法&#xff0c;包含动态障碍物处理、多步预测和启发式函数优化等方面的代码实现。 代码实现 import heapq impo…...

MySQL 8版本认证问题

目录 问题&#xff1a; Public Key Retrieval is not allowed原因&#xff1a; mysql 8.0 调整身份认证机制解决方法&#xff08;三种&#xff09; 问题&#xff1a; Public Key Retrieval is not allowed 连接MySQL8数据库的时候&#xff0c;报错内容如下&#xff1a;“Publi…...

Android 开发APP中参数配置与读取总结

以使用MQTT配置的参数 MQTT_BROKER_UR 、MQTT_USER_NAME、 MQTT_PASSWORD为例&#xff0c;说明配置设置和读取应用 项目中使用系统参数&#xff08;如环境变量和gradle.properties文件中的属性&#xff09;在Gradle构建脚本中&#xff0c;以下是一个详细的操作文档资料&…...

Scala 语法入门

Scala语法入门 1. 定义变量2. 定义方法3. 闭包4. 声明字符串5. 声明数组6. 声明集合7. 异常处理 1. 定义变量 &#xff08;变量的类型在变量名之后等号之前声明&#xff09; 不可变变量(val) 类似于 Java 中的 final 变量&#xff0c;即一旦赋值后&#xff0c;其值不能再被改…...

python中的flask框架

Flask 是一个用Python编写的轻量级Web应用框架 基于WSGI和Jinja2模板引擎 被称为“微框架”&#xff0c;其核心功能简单&#xff0c;不捆绑数据库管理、表单验证等功能&#xff0c;而是通过扩展来增加其他功能 Flask提供最基本的功能&#xff0c;不强制使用特定工具或库 通…...

【redis】缓存设计规范

本文是 Redis 键值设计的 14 个核心规范与最佳实践&#xff0c;按重要程度分层说明&#xff1a; 一、通用数据类型选择 这里我们先给出常规的选择路径图。 以下是对每个步骤的分析&#xff1a; 是否需要排序&#xff1f;&#xff1a; zset&#xff08;有序集合&#xff09;用…...

归一化与伪彩:LabVIEW图像处理的区别

在LabVIEW的图像处理领域&#xff0c;归一化&#xff08;Normalization&#xff09;和伪彩&#xff08;Pseudo-coloring&#xff09;是两个不同的概念&#xff0c;虽然它们都涉及图像像素值的调整&#xff0c;但目的和实现方式截然不同。归一化用于调整像素值的范围&#xff0c…...

DeepSeek大模型本地部署实战

1. 下载并安装Ollama 打开浏览器&#xff1a;使用你常用的浏览器&#xff08;如Chrome、Firefox等&#xff09;访问Ollama的官方网站。无需特殊网络环境&#xff0c;直接搜索“Ollama”即可找到。 登录与下载&#xff1a;进入Ollama官网后&#xff0c;点击右上角的“Download…...

deepseek+kimi自动生成ppt

打开deepseek官网&#xff0c;输入详细的需求&#xff0c;让他生成个ppt 接着deepseek开始思考生成了 接着复制生成了的内容 打开kimi粘贴刚才deepseek生成的内容 可以一键生成啦&#xff0c;下载编辑使用吧...

集成SwanLab与HuggingFace TRL:跟踪与优化强化学习实验

文章目录 1. 引入SwanLabCallback2. 传入Trainer3. 完整案例代码4. GUI效果展示 TRL (Transformers Reinforcement Learning&#xff0c;用强化学习训练Transformers模型) 是一个领先的Python库&#xff0c;旨在通过监督微调&#xff08;SFT&#xff09;、近端策略优化&#xf…...

cefsharp131升级132测试(WinForms.NETCore)

一、升级&#xff08;Nuget&#xff09; 版本说明&#xff08;readme&#xff09;:最低.NET Core3.1 (NET5.0) Visual C 2019 Redist 二、试运行、兼容性测试 三、后记说明 支持H264版本推荐版本63,79,84,88,100,111,125&#xff08;支持h264和pdf预览&#xff09; 其他H264版…...

Gitee AI上线:开启免费DeepSeek模型新时代

Gitee Al上线&#xff0c;并宣布开启免费DeepSeek模型的时代&#xff0c;这是一个非常值得关注的消息&#xff0c;因 为它标志着国内在AI领域的一个重要发展。DeepSeek模型是由阿里巴巴达摩院开发的&#xff0c;旨 在提供强大的自然语言处理(NLP)能力。下面是一些关于这一事件…...

nginx常用命令及补充

在Linux环境下nginx常用命令如下&#xff1a; 1、查看nginx版本号命令 nginx -v 2、查找nginx配置文件路径已经检查配置文件是否正确 nginx -t 3、查找nginx安装目录 which nginx 4、查看nginx进程 ps -ef|grep nginx 5、进入到nginx的sbin目录后&#xff0c;执行一下…...

自动驾驶---聊聊传统规控和端到端

1 背景 在自动驾驶领域中&#xff0c;端到端模型的兴起确实对传统的规划控制方法&#xff08;笔者并不同意网上以Rule-Base称呼传统规控&#xff0c;传统的规控其实也使用了很多优化算法和博弈算法&#xff09;产生了挑战&#xff0c;但这就意味着传统规控方法就完全没有应用了…...

node.js + html + Sealos容器云 搭建简易多人实时聊天室demo 带源码

node.js html Sealos容器云 搭建简易多人实时聊天室demo 带源码 前言功能介绍&#xff08;demo演示&#xff09;sealos官网配置node.js 编写服务端代码前端ui 调用接口整体项目目录部署到服务器 前言 hello哦盆友们&#xff0c;这次我们来十几行代码做一个超简单的多人聊天…...

OpenFeign远程调用返回的是List<T>类型的数据

在使用 OpenFeign 进行远程调用时&#xff0c;如果接口返回的是 List 类型的数据&#xff0c;可以通过以下方式处理&#xff1a; 直接定义返回类型为List Feign 默认支持 JSON 序列化/反序列化&#xff0c;如果服务端返回的是 List的JSON格式数据&#xff0c;可以直接在 Feig…...

PCL 计算多边形的面积【2025最新版】

目录 一、算法原理1、概述2、主要函数3、函数源码二、代码实现三、结果展示博客长期更新,本文最近更新时间为:2025年1月17日。 一、算法原理 1、概述 根据给定的多边形的点云计算多边形的面积 A r e a = 1 2 ∑...

Vue3+AI聊天室:如何实现消息自动滚动和流式响应?

Vue3AI聊天室&#xff1a;消息自动滚动与流式响应的工程实践 引言&#xff1a;当Vue3遇见AI对话 在构建现代化AI聊天应用时&#xff0c;流畅的交互体验往往比功能堆砌更重要。想象这样一个场景&#xff1a;用户发送问题后&#xff0c;界面立即开始逐字显示AI回复&#xff0c;同…...

如何使用Postman,通过Mock的方式测试我们的API

&#x1f345; 点击文末小卡片&#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 这篇文章将教会大家如何利用 postman&#xff0c;通过 Mock 的方式测试我们的 API。什么是 MockMock 是一项特殊的测试技巧&#xff0c;可以在没有依赖项的情况下进…...

一文读懂大模型,彻底告别 AI 焦虑 | 零门槛

今天&#xff0c;不聊复杂代码、不晒专业论文&#xff0c;用最直白的语言&#xff0c;带非技术背景的你彻底读懂大模型&#xff1a;核心逻辑、实用场景、产品选型&#xff0c;以及普通人应对AI浪潮的正确姿势。全文干货密集&#xff0c;建议收藏转发&#xff0c;读完摆脱AI焦虑…...

新手友好:在快马平台用mc、jc相关案例轻松上手前端开发

作为一个刚接触前端开发的新手&#xff0c;我最近在InsCode(快马)平台尝试做了一个特别适合练手的小工具——代码行数统计器。这个项目用最基础的HTML、CSS和JavaScript实现&#xff0c;但包含了前端开发的几个核心概念&#xff0c;特别适合想通过实际案例学习的朋友。 项目功能…...

5分钟搞定OpenClaw+GLM-4.7-Flash:星图平台一键部署体验

5分钟搞定OpenClawGLM-4.7-Flash&#xff1a;星图平台一键部署体验 1. 为什么选择云端部署OpenClaw 作为一个长期折腾本地AI部署的技术爱好者&#xff0c;我深知在个人电脑上配置OpenClaw的痛处。从Node.js版本冲突到模型权重下载失败&#xff0c;再到各种依赖库缺失&#xf…...

编译原理避坑指南:自顶向下语法分析的5个常见错误及解决方法

编译原理避坑指南&#xff1a;自顶向下语法分析的5个常见错误及解决方法 第一次接触自顶向下语法分析时&#xff0c;我盯着那个无限循环的递归文法整整三天没想明白——为什么明明按照教材步骤操作&#xff0c;程序却始终报错&#xff1f;直到助教指出我忽略了间接左递归的隐蔽…...

硬盘监控与健康管理:DiskInfo全方位使用指南

硬盘监控与健康管理&#xff1a;DiskInfo全方位使用指南 【免费下载链接】DiskInfo DiskInfo based on CrystalDiskInfo 项目地址: https://gitcode.com/gh_mirrors/di/DiskInfo 在数字化时代&#xff0c;硬盘故障可能导致珍贵数据永久丢失。DiskInfo作为一款基于Crysta…...

解锁汽车ECU诊断新可能:ECUBus-Pro开源工具的全场景应用指南

解锁汽车ECU诊断新可能&#xff1a;ECUBus-Pro开源工具的全场景应用指南 【免费下载链接】ECUBus ECU bus tool, UDS over CAN, CAN-FD, Ethernet and so on. 项目地址: https://gitcode.com/gh_mirrors/ec/ECUBus ECUBus-Pro是一款功能强大的开源汽车ECU开发工具&#…...

FLUX.1-dev像素生成器效果对比:不同Scale值对像素结构强度影响实测

FLUX.1-dev像素生成器效果对比&#xff1a;不同Scale值对像素结构强度影响实测 1. 像素艺术生成技术概述 像素幻梦&#xff08;Pixel Dream Workshop&#xff09;是基于FLUX.1-dev扩散模型构建的专业像素艺术生成工具。它采用16-bit现代明亮风格设计&#xff0c;为创作者提供…...

PowerBuilder老系统维护指南:PB12.5连接现代数据库(如MySQL 8.0)的避坑实操

PowerBuilder老系统维护实战&#xff1a;PB12.5连接MySQL 8.0的七个关键步骤 当技术栈的代际差异超过十年&#xff0c;每一次数据库连接尝试都可能演变成一场跨越时空的调试马拉松。那些在2006年运行良好的PB12.5应用&#xff0c;今天面对MySQL 8.0的SSL加密要求和UTF8MB4字符集…...