cjson的介绍以及使用方式?

cjson的介绍以及使用方式?

在嵌入式系统中,JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,常用于设备与服务器之间的数据通信。cJSON 是一个用 C 语言实现的轻量级 JSON 解析和生成库,因其简单高效、资源占用低,非常适合嵌入式系统。下面我将详细介绍 cJSON 的功能、使用方法、适用场景,并通过经典示例帮助你理解其应用。

一、cJSON 是什么?为什么用它?

1. cJSON 简介

cJSON 是一个开源的 C 语言库,专门用于解析和生成 JSON 数据。它由 Dave Gamble 开发,代码简洁,易于移植,无需外部依赖,特别适合资源受限的嵌入式系统。cJSON 的主要功能包括:

解析 JSON:将 JSON 字符串解析为 C 语言中的数据结构。

生成 JSON:将 C 语言中的数据结构转换为 JSON 字符串。

操作 JSON:支持增删改查 JSON 对象、数组等。

2. 为什么在嵌入式系统中使用 cJSON?

轻量级:cJSON 代码量小,编译后占用空间少,适合内存受限的嵌入式设备(如 MCU)。

无依赖:纯 C 实现,易于移植到各种嵌入式平台(如 STM32、ESP32 等)。

高效:解析和生成 JSON 的性能较高,满足实时性要求。

简单易用:API 设计直观,开发者可以快速上手。

开源免费:MIT 许可证,适合商业和非商业项目。

3. 适用场景

cJSON 常用于以下嵌入式场景:

物联网(IoT)设备:设备与云端通过 JSON 格式交换数据,如传感器数据上传、远程配置下发。

通信协议:在 HTTP、MQTT、WebSocket 等协议中,JSON 作为数据载体,cJSON 用于处理这些数据。

配置文件解析:嵌入式设备使用 JSON 格式存储配置参数,cJSON 用于读取和修改。

调试和日志:将设备状态以 JSON 格式输出,便于调试和分析。

二、cJSON 的核心功能和数据结构

1. cJSON 的数据结构

cJSON 使用一个核心结构体 cJSON 来表示 JSON 数据,支持以下类型:

基本类型:cJSON_Number(数字)、cJSON_String(字符串)、cJSON_True/cJSON_False(布尔值)、cJSON_Null(空值)。

复合类型:cJSON_Object(对象)、cJSON_Array(数组)。

cJSON 结构体的定义(简化版)如下:

typedef struct cJSON {

struct cJSON *next, *prev; // 用于链表,数组或对象中的元素链接

struct cJSON *child; // 子节点(对象或数组的子元素)

int type; // 数据类型(如 cJSON_Number、cJSON_String 等)

char *valuestring; // 字符串值

int valueint; // 整数值

double valuedouble; // 浮点数值

char *string; // 键名(仅对象中使用)

} cJSON;

2. 核心 API

以下是 cJSON 常用的 API 函数,分为解析、生成和操作三大类:

解析 JSON:

cJSON_Parse(const char *value):将 JSON 字符串解析为 cJSON 结构。

cJSON_GetObjectItem(cJSON *object, const char *string):获取对象中指定键的值。

cJSON_GetArrayItem(cJSON *array, int index):获取数组中指定索引的元素。

生成 JSON:

cJSON_CreateObject():创建空 JSON 对象。

cJSON_CreateArray():创建空 JSON 数组。

cJSON_CreateString(const char *string):创建字符串节点。

cJSON_CreateNumber(double num):创建数字节点。

cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item):向对象添加键值对。

cJSON_Print(cJSON *item):将 cJSON 结构转换为 JSON 字符串。

操作 JSON:

cJSON_Delete(cJSON *item):释放 cJSON 结构内存。

cJSON_ReplaceItemInObject(cJSON *object, const char *string, cJSON *newitem):替换对象中的键值。

cJSON_DetachItemFromArray(cJSON *array, int which):从数组中移除元素。

三、如何使用 cJSON?

1. 环境准备

获取 cJSON:从 GitHub(https://github.com/DaveGamble/cJSON)下载 cJSON.c 和 cJSON.h。

集成到项目:

将 cJSON.c 和 cJSON.h 加入嵌入式项目。

在编译器中确保包含标准 C 库(如 string.h、stdlib.h)。

对于资源极度受限的系统,可通过修改 cJSON.h 中的宏(如禁用某些功能)优化内存占用。

编译:将 cJSON 源码编译到你的嵌入式项目中,通常只需添加 cJSON.c 到项目文件列表。

2. 使用步骤

解析 JSON 字符串:

使用 cJSON_Parse 解析 JSON 字符串。

检查解析结果是否为空(防止无效 JSON)。

使用 cJSON_GetObjectItem 或 cJSON_GetArrayItem 提取数据。

生成 JSON 数据:

使用 cJSON_Create* 函数创建 JSON 节点。

使用 cJSON_AddItemTo* 函数构建对象或数组。

使用 cJSON_Print 转换为 JSON 字符串。

释放内存:

使用 cJSON_Delete 释放 cJSON 结构,避免内存泄漏。

四、经典示例

以下通过两个经典嵌入式场景示例,展示 cJSON 的使用方法。

示例 1:解析传感器数据的 JSON 字符串

假设设备接收到以下 JSON 数据,表示传感器状态:

{

"temperature": 25.5,

"humidity": 60,

"status": "OK"

}

代码实现:

#include

#include

#include "cJSON.h"

void parse_sensor_data(const char *json_str) {

// 解析 JSON 字符串

cJSON *root = cJSON_Parse(json_str goroutine

if (root == NULL) {

printf("Failed to parse JSON\n");

return;

}

// 提取数据

cJSON *temp = cJSON_GetObjectItem(root, "temperature");

cJSON *hum = cJSON_GetObjectItem(root, "humidity");

cJSON *status = cJSON_GetObjectItem(root, "status");

if (temp && hum && status) {

printf("Temperature: %.1f\n", temp->valuedouble);

printf("Humidity: %d\n", hum->valueint);

printf("Status: %s\n", status->valuestring);

} else {

printf("Missing fields in JSON\n");

}

// 释放内存

cJSON_Delete(root);

}

int main() {

const char *json_str = "{\"temperature\": 25.5, \"humidity\": 60, \"status\": \"OK\"}";

parse_sensor_data(json_str);

return 0;

}

解释:

cJSON_Parse 将 JSON 字符串解析为 cJSON 结构。

使用 cJSON_GetObjectItem 提取 temperature、humidity 和 status 的值。

检查每个字段是否存在,防止访问空指针。

最后用 cJSON_Delete 释放内存。

适用场景:嵌入式设备从云端接收 JSON 格式的传感器数据,解析后用于控制逻辑(如判断温度是否超标)。

输出:

Temperature: 25.5

Humidity: 60

Status: OK

示例 2:生成设备状态的 JSON 字符串

假设设备需要生成以下 JSON 数据发送到服务器:

{

"device_id": "DEV001",

"battery": 85,

"sensors": [

{"type": "temp", "value": 26.2},

{"type": "hum", "value": 58}

]

}

代码实现:

#include

#include

#include "cJSON.h"

void create_device_status() {

// 创建 JSON 对象

cJSON *root = cJSON_CreateObject();

// 添加基本字段

cJSON_AddStringToObject(root, "device_id", "DEV001");

cJSON_AddNumberToObject(root, "battery", 85);

// 创建传感器数组

cJSON *sensors = cJSON_CreateArray();

cJSON_AddItemToObject(root, "sensors", sensors);

// 添加第一个传感器数据

cJSON *sensor1 = cJSON_CreateObject();

cJSON_AddStringToObject(sensor1, "type", "temp");

cJSON_AddNumberToObject(sensor1, "value", 26.2);

cJSON_AddItemToArray(sensors, sensor1);

// 添加第二个传感器数据

cJSON *sensor2 = cJSON_CreateObject();

cJSON_AddStringToObject(sensor2, "type", "hum");

cJSON_AddNumberToObject(sensor2, "value", 58);

cJSON_AddItemToArray(sensors, sensor2);

// 转换为 JSON 字符串

char *json_str = cJSON_Print(root);

printf("%s\n", json_str);

// 释放内存

cJSON_Delete(root);

free(json_str);

}

int main() {

create_device_status();

return 0;

}

解释:

使用 cJSON_CreateObject 和 cJSON_CreateArray 创建 JSON 结构。

通过 cJSON_Add* 函数添加键值对和数组元素。

cJSON_Print 生成 JSON 字符串,供设备通过网络发送。

释放 root 和 json_str 的内存,防止泄漏。

适用场景:嵌入式设备(如 ESP32)生成状态数据,通过 MQTT 或 HTTP 发送到云端。

输出:

{

"device_id": "DEV001",

"battery": 85,

"sensors": [{

"type": "temp",

"value": 26.2

}, {

"type": "hum",

"value": 58

}]

}

五、在嵌入式系统中的使用注意事项

内存管理:

嵌入式系统内存有限,始终使用 cJSON_Delete 释放 cJSON 结构。

使用 cJSON_PrintUnformatted 生成无格式 JSON 字符串,节省空间。

对于极低内存设备,可通过 #define cJSON_Malloc 自定义内存分配函数,优化内存使用。

错误处理:

检查 cJSON_Parse 返回值是否为 NULL。

使用 cJSON_Is* 函数(如 cJSON_IsNumber、cJSON_IsString)验证字段类型。

性能优化:

避免频繁解析和生成大型 JSON 数据。

对于固定格式的 JSON,可使用静态结构减少动态分配。

移植性:

cJSON 默认使用标准 C 库的 malloc 和 free,确保嵌入式平台的 C 库支持这些函数。

若平台不支持浮点数运算,可禁用 cJSON_Number 的浮点支持(修改 cJSON.h)。

六、适用场景和经典案例

物联网设备与云端通信:

场景:ESP32 采集温湿度数据,通过 MQTT 协议以 JSON 格式发送到 AWS IoT。

实现:使用示例 2 生成 JSON 数据,调用 MQTT 库发送。

优点:JSON 格式通用,易于云端解析;cJSON 轻量,适合 ESP32 的 520KB SRAM。

设备配置管理:

场景:STM32 设备从 Flash 读取 JSON 格式的配置文件,调整运行参数。

实现:使用示例 1 解析 JSON,提取参数值。

优点:JSON 格式直观,易于手动编辑配置文件。

调试日志输出:

场景:设备通过串口输出 JSON 格式的运行状态,便于调试工具解析。

实现:类似示例 2,生成 JSON 后通过 UART 输出。

优点:结构化日志便于自动化分析。

七、总结

cJSON 是一个轻量、简单、高效的 JSON 解析和生成库,非常适合嵌入式系统。其核心优势在于无依赖、易移植和低资源占用。通过解析和生成 JSON,cJSON 能满足物联网设备通信、配置管理等需求。使用时需注意内存管理和错误处理,尤其在资源受限的嵌入式环境中。

相关典藏

墨绿色可以与许多颜色搭配在一起,但这4种搭配建议很好看
美国的国土面积到底有多大?可能真的比我们国家大一点
365bet博彩官网

美国的国土面积到底有多大?可能真的比我们国家大一点

📅 02-03 👁️‍🗨️ 1093
腹部开刀手术后多久能参加体育锻炼
365bet博彩官网

腹部开刀手术后多久能参加体育锻炼

📅 08-19 👁️‍🗨️ 808