十二、【ESP32全栈开发指南: IDF开发环境下cJSON使用】
一、JSON简介
JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,具有以下核心特性:
- 完全独立于编程语言的文本格式
- 易于人阅读和编写
- 易于机器解析和生成
- 基于ECMAScript标准子集
1.1 JSON语法规则
{"name": "ESP32","cores": 2,"features": ["WiFi", "Bluetooth", "Low Power"],"metadata": {"voltage": 3.3,"package": "QFN48"}
}
- 对象:花括号
{}
包裹的键值对集合 - 数组:方括号
[]
包裹的值列表 - 键名:必须使用双引号包裹
- 分隔符:键值对用逗号分隔
1.2 支持的数据类型
类型 | 示例 |
---|---|
字符串 | “ESP32” |
数值 | 3.3, 240 |
布尔值 | true, false |
对象 | { “key”: “value” } |
数组 | [1, 2, 3] |
null | null |
二、添加cJSON库
在ESP-IDF环境中,cJSON库已集成在组件中:
// 包含头文件
#include "cJSON.h"// CMakeLists.txt 配置
idf_component_register(...REQUIRES cJSON
)
三、生成JSON数据
3.1 创建JSON结构体
cJSON *root = cJSON_CreateObject(); // 创建根对象
cJSON *sensor_data = cJSON_CreateObject(); // 创建子对象
3.2 添加各种类型数据
// 添加基本类型
cJSON_AddStringToObject(root, "device", "ESP32-S3");
cJSON_AddNumberToObject(root, "temperature", 25.6);
cJSON_AddBoolToObject(root, "connected", true);// 添加嵌套对象
cJSON_AddItemToObject(root, "sensor", sensor_data);
cJSON_AddStringToObject(sensor_data, "type", "DHT11");
cJSON_AddNumberToObject(sensor_data, "humidity", 45.7);// 添加整型数组
int gpio_pins[3] = {12, 13, 14};
cJSON *pins_array = cJSON_CreateIntArray(gpio_pins, 3);
cJSON_AddItemToObject(root, "gpio_pins", pins_array);// 添加对象数组
cJSON *networks = cJSON_CreateArray();
for (int i = 0; i < 2; i++) {cJSON *network = cJSON_CreateObject();cJSON_AddStringToObject(network, "ssid", (i == 0) ? "HomeWiFi" : "OfficeAP");cJSON_AddNumberToObject(network, "rssi", -65 + i*10);cJSON_AddItemToArray(networks, network);
}
cJSON_AddItemToObject(root, "networks", networks);
3.3 输出与序列化
// 格式化输出
char *json_str = cJSON_Print(root);
ESP_LOGI("JSON", "Generated JSON:\n%s", json_str);/* 输出结果:
{"device": "ESP32-S3","temperature": 25.6,"connected": true,"sensor": {"type": "DHT11","humidity": 45.7},"gpio_pins": [12, 13, 14],"networks": [{"ssid": "HomeWiFi", "rssi": -65},{"ssid": "OfficeAP", "rssi": -55}]
}
*/
3.4 内存管理
cJSON_free(json_str); // 释放打印字符串
cJSON_Delete(root); // 递归释放整个JSON树
重要提示:
cJSON_Delete()
会递归释放所有子节点,只需在根节点调用一次
四、解析JSON数据
4.1 基础解析流程
const char *json_str = "{\"status\":\"active\",\"uptime\":3600}";cJSON *root = cJSON_Parse(json_str);
if (root == NULL) {const char *error_ptr = cJSON_GetErrorPtr();if (error_ptr != NULL) {ESP_LOGE("JSON", "Error before: %s", error_ptr);}return;
}// 提取数据
cJSON *status = cJSON_GetObjectItem(root, "status");
cJSON *uptime = cJSON_GetObjectItem(root, "uptime");if (cJSON_IsString(status)) {ESP_LOGI("JSON", "Status: %s", status->valuestring);
}if (cJSON_IsNumber(uptime)) {ESP_LOGI("JSON", "Uptime: %d seconds", uptime->valueint);
}cJSON_Delete(root);
4.2 解析复杂结构
// 示例JSON
const char *config_str = "{ \"sensors\": [ \{\"type\":\"temperature\", \"pin\":12}, \{\"type\":\"humidity\", \"pin\":14} \
]}";cJSON *root = cJSON_Parse(config_str);
cJSON *sensors = cJSON_GetObjectItem(root, "sensors");if (cJSON_IsArray(sensors)) {int sensor_count = cJSON_GetArraySize(sensors);for (int i = 0; i < sensor_count; i++) {cJSON *sensor = cJSON_GetArrayItem(sensors, i);cJSON *type = cJSON_GetObjectItem(sensor, "type");cJSON *pin = cJSON_GetObjectItem(sensor, "pin");if (cJSON_IsString(type) && cJSON_IsNumber(pin)) {ESP_LOGI("SENSOR", "Type: %s, GPIO: %d", type->valuestring, pin->valueint);}}
}
4.3 错误处理技巧
// 安全获取对象项
cJSON* safe_get_object(cJSON *obj, const char *key, cJSON_type type) {cJSON *item = cJSON_GetObjectItem(obj, key);if (!item) {ESP_LOGW("JSON", "Missing key: %s", key);return NULL;}if (item->type != type) {ESP_LOGW("JSON", "Type mismatch for %s", key);return NULL;}return item;
}// 使用示例
cJSON *temp = safe_get_object(root, "temperature", cJSON_Number);
if (temp) {// 安全使用数据
}
五、实战技巧与最佳实践
5.1 内存优化技巧
// 使用缓冲器避免碎片化
char json_buffer[512];
cJSON *root = cJSON_CreateObject();
cJSON_AddStringToObject(root, "message", "Hello JSON");// 直接打印到固定缓冲区
cJSON_PrintPreallocated(root, json_buffer, sizeof(json_buffer), true);
ESP_LOGI("JSON", "Compact JSON: %s", json_buffer);// 释放资源
cJSON_Delete(root);
5.2 常用库函数速查
函数 | 说明 |
---|---|
cJSON_Parse() | 解析JSON字符串 |
cJSON_Print() | 生成格式化JSON字符串 |
cJSON_PrintUnformatted() | 生成紧凑型JSON字符串 |
cJSON_GetObjectItem() | 获取对象属性 |
cJSON_GetArraySize() | 获取数组长度 |
cJSON_GetArrayItem() | 获取数组元素 |
cJSON_Is...() | 类型检查函数族 |
cJSON_Add...ToObject() | 添加各类数据到对象 |
cJSON_Create...() | 创建各类JSON元素 |
5.3 常见问题解决方案
- 内存泄漏:确保每个
cJSON_Create*()
都有对应的cJSON_Delete()
- 无效指针:检查
cJSON_Parse()
返回值是否为NULL - 类型错误:使用
cJSON_IsNumber()
等函数验证数据类型 - 键名错误:使用
cJSON_HasObjectItem()
检查键是否存在
性能提示:在实时系统中避免频繁解析大型JSON,可考虑预解析或二进制格式
结语
cJSON为ESP32提供了高效的JSON处理能力,本文涵盖了从基础操作到高级技巧的全方位内容。实际开发时请注意:
- 始终进行错误检查
- 在解析前验证JSON格式有效性
- 使用预分配缓冲区处理大数据
- 及时释放内存资源
示例代码兼容ESP-IDF v4.4+,可在GitHub获取完整工程:esp32-cjson-demo
附:内存管理示意图
cJSON_CreateObject()├── cJSON_AddStringToObject() // 分配字符串内存├── cJSON_CreateArray() // 分配数组内存│ └── cJSON_CreateObject() // 嵌套对象└── ...
cJSON_Print() // 分配输出字符串内存
cJSON_free() // 释放输出字符串
cJSON_Delete() // 递归释放所有节点
相关文章:
十二、【ESP32全栈开发指南: IDF开发环境下cJSON使用】
一、JSON简介 JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,具有以下核心特性: 完全独立于编程语言的文本格式易于人阅读和编写易于机器解析和生成基于ECMAScript标准子集 1.1 JSON语法规则 {"name"…...

Qt/C++学习系列之列表使用记录
Qt/C学习系列之列表使用记录 前言列表的初始化界面初始化设置名称获取简单设置 单元格存储总结 前言 列表的使用主要基于QTableWidget控件,同步使用QTableWidgetItem进行单元格的设置,最后可以使用QAxObject进行单元格的数据读出将数据进行存储。接下来…...
【Pandas】pandas DataFrame dropna
Pandas2.2 DataFrame Missing data handling 方法描述DataFrame.fillna([value, method, axis, …])用于填充 DataFrame 中的缺失值(NaN)DataFrame.backfill(*[, axis, inplace, …])用于**使用后向填充(即“下一个有效观测值”)…...

基于django+vue的健身房管理系统-vue
开发语言:Python框架:djangoPython版本:python3.8数据库:mysql 5.7数据库工具:Navicat12开发软件:PyCharm 系统展示 会员信息管理 员工信息管理 会员卡类型管理 健身项目管理 会员卡管理 摘要 健身房管理…...

Yolo11改进策略:Block改进|FCM,特征互补映射模块|AAAI 2025|即插即用
1 论文信息 FBRT-YOLO(Faster and Better for Real-Time Aerial Image Detection)是由北京理工大学团队提出的专用于航拍图像实时目标检测的创新框架,发表于AAAI 2025。论文针对航拍场景中小目标检测的核心难题展开研究,重点解决…...
【系统架构设计师-2025上半年真题】综合知识-参考答案及部分详解(回忆版)
更多内容请见: 备考系统架构设计师-专栏介绍和目录 文章目录 【第1题】【第2题】【第3题】【第4题】【第5题】【第6题】【第7题】【第8题】【第9题】【第10题】【第11题】【第12题】【第13题】【第14题】【第15题】【第16题】【第17题】【第18题】【第19题】【第20~21题】【第…...

简单聊下阿里云DNS劫持事件
阿里云域名被DNS劫持事件 事件总结 根据ICANN规则,域名注册商(Verisign)认定aliyuncs.com域名下的部分网站被用于非法活动(如传播恶意软件);顶级域名DNS服务器将aliyuncs.com域名的DNS记录统一解析到shado…...
LTR-381RGB-01RGB+环境光检测应用场景及客户类型主要有哪些?
RGB环境光检测 功能,在应用场景及客户类型: 1. 可应用的儿童玩具类型 (1) 智能互动玩具 功能:通过检测环境光或物体颜色触发互动(如颜色识别积木、光感音乐盒)。 客户参考: LEGO(乐高&#x…...

循环语句之while
While语句包括一个循环条件和一段代码块,只要条件为真,就不断 循环执行代码块。 1 2 3 while (条件) { 语句 ; } var i 0; while (i < 100) {console.log(i 当前为: i); i i 1; } 下面的例子是一个无限循环,因…...

机器学习复习3--模型评估
误差与过拟合 我们将学习器对样本的实际预测结果与样本的真实值之间的差异称为:误差(error)。 误差定义: ①在训练集上的误差称为训练误差(training error)或经验误差(empirical error&#x…...

联邦学习带宽资源分配
带宽资源分配是指在网络中如何合理分配有限的带宽资源,以满足各个通信任务和用户的需求,尤其是在多用户共享带宽的情况下,如何确保各个设备或用户的通信需求得到高效且公平的满足。带宽是网络中的一个重要资源,通常指的是单位时间…...

今日行情明日机会——20250609
上证指数放量上涨,接近3400点,个股涨多跌少。 深证放量上涨,但有个小上影线,相对上证走势更弱。 2025年6月9日涨停股主要行业方向分析(基于最新图片数据) 1. 医药(11家涨停) 代表标…...

GC1808:高性能音频ADC的卓越之选
在音频处理领域,高质量的音频模数转换器(ADC)是实现精准音频数字化的关键。GC1808,一款96kHz、24bit立体声音频ADC,以其卓越的性能和高性价比脱颖而出,成为众多音频设备制造商的理想选择。 GC1808集成了64倍…...

生产管理系统开发:专业软件开发公司的实践与思考
生产管理系统开发的关键点 在当前制造业智能化升级的转型背景下,生产管理系统开发正逐步成为企业优化生产流程的重要技术手段。不同行业、不同规模的企业在推进生产管理数字化转型过程中,面临的挑战存在显著差异。本文结合具体实践案例,分析…...

VASP软件在第一性原理计算中的应用-测试GO
VASP软件在第一性原理计算中的应用 VASP是由维也纳大学Hafner小组开发的一款功能强大的第一性原理计算软件,广泛应用于材料科学、凝聚态物理、化学和纳米技术等领域。 VASP的核心功能与应用 1. 电子结构计算 VASP最突出的功能是进行高精度的电子结构计算ÿ…...

Centos 7 服务器部署多网站
一、准备工作 安装 Apache bash sudo yum install httpd -y sudo systemctl start httpd sudo systemctl enable httpd创建网站目录 假设部署 2 个网站,目录结构如下: bash sudo mkdir -p /var/www/site1/html sudo mkdir -p /var/www/site2/html添加测试…...

从数据报表到决策大脑:AI重构电商决策链条
在传统电商运营中,决策链条往往止步于“数据报表层”:BI工具整合历史数据,生成滞后一周甚至更久的销售分析,运营团队凭经验预判需求。当爆款突然断货、促销库存积压时,企业才惊觉标准化BI的决策时差正成为增长瓶颈。 一…...
在ubuntu等linux系统上申请https证书
使用 Certbot 自动申请 安装 Certbot Certbot 是 Let’s Encrypt 官方推荐的自动化工具,支持多种操作系统和服务器环境。 在 Ubuntu/Debian 上: sudo apt update sudo apt install certbot申请证书 纯手动方式(不自动配置)&…...

(12)-Fiddler抓包-Fiddler设置IOS手机抓包
1.简介 Fiddler不但能截获各种浏览器发出的 HTTP 请求,也可以截获各种智能手机发出的HTTP/ HTTPS 请求。 Fiddler 能捕获Android 和 Windows Phone 等设备发出的 HTTP/HTTPS 请求。同理也可以截获iOS设备发出的请求,比如 iPhone、iPad 和 MacBook 等苹…...
【R语言编程——数据调用】
这里写自定义目录标题 可用库及数据集外部数据导入方法查看数据集信息 在R语言中,有多个库支持调用内置数据集或外部数据,包括studentdata等教学或示例数据集。以下是常见的库和方法: 可用库及数据集 openintro库 该库包含多个教学数据集&a…...

第2课 SiC MOSFET与 Si IGBT 静态特性对比
2.1 输出特性对比 2.2 转移特性对比 2.1 输出特性对比 器件的输出特性描述了当温度和栅源电压(栅射电压)为某一具体数值时,漏极电流(集电极电流...

MCP和Function Calling
MCP MCP(Model Context Protocol,模型上下文协议) ,2024年11月底,由 Anthropic 推出的一种开放标准,旨在统一大模型与外部数据源和工具之间的通信协议。MCP 的主要目的在于解决当前 AI 模型因数据孤岛限制而…...
软件工程教学评价
王海林老师您好。 您的《软件工程》课程成功地将宏观的理论与具体的实践相结合。上半学期的理论教学中,您通过丰富的实例,将“高内聚低耦合”、SOLID原则等抽象概念解释得十分透彻,让这些理论不再是停留在纸面的名词,而是可以指导…...

解密鸿蒙系统的隐私护城河:从权限动态管控到生物数据加密的全链路防护
摘要 本文以健康管理应用为例,展示鸿蒙系统如何通过细粒度权限控制、动态权限授予、数据隔离和加密存储四大核心机制,实现复杂场景下的用户隐私保护。我们将通过完整的权限请求流程和敏感数据处理代码,演示鸿蒙系统如何平衡功能需求与隐私安…...
前端打包工具简单介绍
前端打包工具简单介绍 一、Webpack 架构与插件机制 1. Webpack 架构核心组成 Entry(入口) 指定应用的起点文件,比如 src/index.js。 Module(模块) Webpack 把项目当作模块图,模块可以是 JS、CSS、图片等…...

SFTrack:面向警务无人机的自适应多目标跟踪算法——突破小尺度高速运动目标的追踪瓶颈
【导读】 本文针对无人机(UAV)视频中目标尺寸小、运动快导致的多目标跟踪难题,提出一种更简单高效的方法。核心创新在于从低置信度检测启动跟踪(贴合无人机场景特性),并改进传统外观匹配算法以关联此类检测…...

STM32 低功耗设计全攻略:PWR 模块原理 + 睡眠 / 停止 / 待机模式实战(串口 + 红外 + RTC 应用全解析)
文章目录 PWRPWR(电源控制模块)核心功能 电源框图上电复位和掉电复位可编程电压监测器低功耗模式模式选择睡眠模式停止模式待机模式 修改主频一、准备工作二、修改主频的核心步骤:宏定义配置三、程序流程:时钟配置函数解析四、注意…...

持续交付的进化:从DevOps到AI驱动的IT新动能
文章目录 一、持续交付的本质:从手动到自动的交付飞跃关键特性案例:电商平台的高效部署 二、持续交付的演进:从CI到AI驱动的未来发展历程 中国…...
Linux信号保存与处理机制详解
Linux信号的保存与处理涉及多个关键机制,以下是详细的总结: 1. 信号的保存 进程描述符(task_struct):每个进程的PCB中包含信号相关信息。 pending信号集:记录已到达但未处理的信号(未决信号&a…...

OpenHarmony标准系统-HDF框架之I2C驱动开发
文章目录 引言I2C基础知识概念和特性协议,四种信号组合 I2C调试手段硬件软件 HDF框架下的I2C设备驱动案例描述驱动Dispatch驱动读写 总结 引言 I2C基础知识 概念和特性 集成电路总线,由串网12C(1C、12C、Inter-Integrated Circuit BUS)行数据线SDA和串…...