xt-sdk 文档 v1.0.3
xt-sdk 嵌入式 SDK API 参考
载入中...
搜索中...
未找到
cJSON - JSON 解析器

版本:1.7.13(第三方库) | 路径: components/cJSON/


一、概述

cJSON 是 Dave Gamble 创建的轻量级 C 语言 JSON 解析器,采用节点树模型。xt-sdk 将其作为第三方组件集成,为配置文件解析、协议数据交换等场景提供 JSON 能力,无需引入额外运行时依赖。

1.1 集成方式

xt-sdk 对上游 cJSON 1.7.13 做了以下适配:

改动 位置 说明
Doxygen 分组 cJSON.h 添加 @defgroup cJSON / @ingroup 公共组件 ,纳入组件文档体系
sprintf 宏映射 cJSON.c #define osSprintf sprintf / #define osSnprintf snprintf ,为后续替换 OS 抽象层预留 hook
符号导出宏 cJSON.h #define CJSON_PUBLIC_cJSON_ (空宏),用于符号可见性控制

除上述适配外,源码与上游保持一致,未做功能裁剪。

1.2 设计原则

  • **零外部依赖**:仅依赖 C 标准库( string.h 、 stdio.h 、 math.h 、 stdlib.h )
  • **调用者管理内存**:解析结果由调用者通过 cJSON_Delete 释放,序列化结果通过 free 或 cJSON_free 释放
  • **可注入分配器**:通过 cJSON_InitHooks 可替换默认 malloc / free ,适配无堆或自定义内存池的嵌入式环境
  • **嵌套保护**: CJSON_NESTING_LIMIT (默认 1000)防止恶意深嵌套 JSON 导致栈溢出

1.3 依赖

依赖 用途
C 标准库 malloc / free / sprintf / snprintf 等基础函数

二、核心概念

2.1 节点树模型

cJSON 将 JSON 文档解析为 cJSON 结构体组成的双向链表树。每个节点包含 next / prev (同级遍历)、 child (子节点访问)、 type (类型标记)以及 valuestring / valueint / valuedouble (值存储)。对象成员的键名存储在 string 字段。

{"name":"test","values":[1,2,3]}
root (Object)
├── "name" → "test" (String)
└── "values" → (Array)
├── 1 (Number)
├── 2 (Number)
└── 3 (Number)

2.2 内存所有权

操作 分配者 释放者 释放方式
cJSON_Parse cJSON 内部 调用者 cJSON_Delete
cJSON_Print / cJSON_PrintUnformatted cJSON 内部 调用者 free 或 cJSON_Hooks.free_fn
cJSON_PrintPreallocated 调用者 调用者 自行管理
cJSON_Create* cJSON 内部 调用者 cJSON_Delete

2.3 引用类型

cJSON_CreateStringReference 和 cJSON_CreateObjectReference 创建的节点不拥有数据指针, cJSON_Delete 不会释放其指向的内存。适用于将已有字符串或 cJSON 节点挂到新树中而不触发深拷贝的场景。


三、API 参考

以下为函数签名大纲,完整的参数说明、返回值、注意事项请查看 cJSON(JSON 解析器) 。

3.1 解析与初始化

函数签名 说明
const char * cJSON_Version(void) 获取 cJSON 版本号字符串
void cJSON_InitHooks(cJSON_Hooks *hooks) 注入自定义 malloc/free
cJSON * cJSON_Parse(const char *value) 解析 JSON 字符串为 cJSON 树
cJSON * cJSON_ParseWithLength(const char *value, size_t buffer_length) 按指定长度解析
cJSON * cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated) 带选项解析
cJSON * cJSON_ParseWithLengthOpts(const char *value, size_t buffer_length, const char **return_parse_end, cJSON_bool require_null_terminated) 带长度和选项解析
const char * cJSON_GetErrorPtr(void) 获取解析错误位置指针

3.2 序列化与释放

函数签名 说明
char * cJSON_Print(const cJSON *item) 格式化输出 JSON 字符串
char * cJSON_PrintUnformatted(const cJSON *item) 紧凑无格式输出
char * cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt) 缓冲策略输出
cJSON_bool cJSON_PrintPreallocated(cJSON *item, char *buffer, int length, cJSON_bool format) 预分配缓冲区输出
void cJSON_Delete(cJSON *item) 删除节点及所有子节点

3.3 查询

函数签名 说明
int cJSON_GetArraySize(const cJSON *array) 数组/对象元素个数
cJSON * cJSON_GetArrayItem(const cJSON *array, int index) 按索引获取数组元素
cJSON * cJSON_GetObjectItem(const cJSON *object, const char *string) 按键名获取对象成员(大小写不敏感)
cJSON * cJSON_GetObjectItemCaseSensitive(const cJSON *object, const char *string) 按键名获取对象成员(大小写敏感)
cJSON_bool cJSON_HasObjectItem(const cJSON *object, const char *string) 检查对象是否包含指定键
char * cJSON_GetStringValue(cJSON *item) 获取字符串值
double cJSON_GetNumberValue(cJSON *item) 获取数值

3.4 类型检查

函数签名 说明
cJSON_bool cJSON_IsInvalid(const cJSON *item) 是否为无效类型
cJSON_bool cJSON_IsFalse(const cJSON *item) 是否为 false
cJSON_bool cJSON_IsTrue(const cJSON *item) 是否为 true
cJSON_bool cJSON_IsBool(const cJSON *item) 是否为布尔类型
cJSON_bool cJSON_IsNull(const cJSON *item) 是否为 null
cJSON_bool cJSON_IsNumber(const cJSON *item) 是否为数值
cJSON_bool cJSON_IsString(const cJSON *item) 是否为字符串
cJSON_bool cJSON_IsArray(const cJSON *item) 是否为数组
cJSON_bool cJSON_IsObject(const cJSON *item) 是否为对象
cJSON_bool cJSON_IsRaw(const cJSON *item) 是否为原始 JSON

3.5 创建节点

函数签名 说明
cJSON * cJSON_CreateNull(void) 创建 null 节点
cJSON * cJSON_CreateTrue(void) 创建 true 节点
cJSON * cJSON_CreateFalse(void) 创建 false 节点
cJSON * cJSON_CreateBool(cJSON_bool boolean) 创建布尔节点
cJSON * cJSON_CreateNumber(double num) 创建数值节点
cJSON * cJSON_CreateString(const char *string) 创建字符串节点
cJSON * cJSON_CreateRaw(const char *raw) 创建原始 JSON 节点
cJSON * cJSON_CreateArray(void) 创建空数组
cJSON * cJSON_CreateObject(void) 创建空对象
cJSON * cJSON_CreateStringReference(const char *string) 创建字符串引用节点(不拥有内存)
cJSON * cJSON_CreateObjectReference(const cJSON *child) 创建对象引用节点
cJSON * cJSON_CreateArrayReference(const cJSON *child) 创建数组引用节点
cJSON * cJSON_CreateIntArray(const int *numbers, int count) 从 int 数组创建 JSON 数组
cJSON * cJSON_CreateFloatArray(const float *numbers, int count) 从 float 数组创建 JSON 数组
cJSON * cJSON_CreateDoubleArray(const double *numbers, int count) 从 double 数组创建 JSON 数组
cJSON * cJSON_CreateStringArray(const char *const *strings, int count) 从字符串数组创建 JSON 数组

3.6 添加与移除

函数签名 说明
cJSON_bool cJSON_AddItemToArray(cJSON *array, cJSON *item) 向数组追加元素
cJSON_bool cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item) 向对象追加成员
cJSON_bool cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item) 向对象追加常量键成员
cJSON_bool cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item) 以引用方式向数组追加元素
cJSON_bool cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item) 以引用方式向对象追加成员
cJSON * cJSON_DetachItemViaPointer(cJSON *parent, cJSON *item) 按指针分离元素
cJSON * cJSON_DetachItemFromArray(cJSON *array, int which) 按索引分离数组元素
void cJSON_DeleteItemFromArray(cJSON *array, int which) 按索引删除数组元素
cJSON * cJSON_DetachItemFromObject(cJSON *object, const char *string) 按键名分离对象成员
cJSON * cJSON_DetachItemFromObjectCaseSensitive(cJSON *object, const char *string) 按键名分离对象成员(大小写敏感)
void cJSON_DeleteItemFromObject(cJSON *object, const char *string) 按键名删除对象成员
void cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const char *string) 按键名删除对象成员(大小写敏感)

3.7 更新

函数签名 说明
cJSON_bool cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem) 在指定位置插入元素
cJSON_bool cJSON_ReplaceItemViaPointer(cJSON *parent, cJSON *item, cJSON *replacement) 按指针替换元素
cJSON_bool cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem) 按索引替换数组元素
cJSON_bool cJSON_ReplaceItemInObject(cJSON *object, const char *string, cJSON *newitem) 按键名替换对象成员
cJSON_bool cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object, const char *string, cJSON *newitem) 按键名替换对象成员(大小写敏感)

3.8 快捷添加到对象

函数签名 说明
cJSON * cJSON_AddNullToObject(cJSON *object, const char *name) 向对象添加 null 成员
cJSON * cJSON_AddTrueToObject(cJSON *object, const char *name) 向对象添加 true 成员
cJSON * cJSON_AddFalseToObject(cJSON *object, const char *name) 向对象添加 false 成员
cJSON * cJSON_AddBoolToObject(cJSON *object, const char *name, cJSON_bool boolean) 向对象添加布尔成员
cJSON * cJSON_AddNumberToObject(cJSON *object, const char *name, double number) 向对象添加数值成员
cJSON * cJSON_AddStringToObject(cJSON *object, const char *name, const char *string) 向对象添加字符串成员
cJSON * cJSON_AddRawToObject(cJSON *object, const char *name, const char *raw) 向对象添加原始 JSON 成员
cJSON * cJSON_AddObjectToObject(cJSON *object, const char *name) 向对象添加子对象
cJSON * cJSON_AddArrayToObject(cJSON *object, const char *name) 向对象添加子数组

3.9 工具与内存

函数签名 说明
cJSON * cJSON_Duplicate(const cJSON *item, cJSON_bool recurse) 深拷贝 cJSON 节点
cJSON_bool cJSON_Compare(const cJSON *a, const cJSON *b, cJSON_bool case_sensitive) 递归比较两个节点是否相等
void cJSON_Minify(char *json) 去除 JSON 字符串中的空白字符
double cJSON_SetNumberHelper(cJSON *object, double number) 设置数值(SetNumberValue 宏的辅助函数)
char * cJSON_SetValuestring(cJSON *object, const char *valuestring) 设置字符串节点的值
void * cJSON_malloc(size_t size) 使用 cJSON 分配器分配内存
void cJSON_free(void *object) 使用 cJSON 分配器释放内存

3.10 宏

宏签名 说明
cJSON_SetIntValue(object, number) 设置整数值(同步更新 valuedouble)
cJSON_SetNumberValue(object, number) 设置数值
cJSON_ArrayForEach(element, array) 遍历数组/对象元素的 for 宏

函数已按"解析 / 序列化 / 创建 / 添加 / 删除 / 查询 / 类型检查 / 宏工具"分组,直接在 doxygen 页面查看。


四、编译配置

宏 默认值 说明
CJSON_NESTING_LIMIT 1000 最大嵌套深度,超出拒绝解析
CJSON_HIDE_SYMBOLS 未定义 隐藏所有导出符号(Windows)
CJSON_EXPORT_SYMBOLS 定义(Windows 默认) dllexport 导出符号
CJSON_IMPORT_SYMBOLS 未定义 dllimport 导入符号
CJSON_API_VISIBILITY 未定义 GCC/Sun 可见性属性控制

五、常见模式

5.1 解析并读取 JSON

const char *json_str = "{\"host\":\"192.168.1.1\",\"port\":8080}";
cJSON *root = cJSON_Parse(json_str);
if (root == NULL) {
const char *err = cJSON_GetErrorPtr();
/* 处理解析错误 */
return;
}
cJSON *host = cJSON_GetObjectItem(root, "host");
cJSON *port = cJSON_GetObjectItem(root, "port");
if (cJSON_IsString(host)) {
printf("host: %s\n", host->valuestring);
}
if (cJSON_IsNumber(port)) {
printf("port: %d\n", port->valueint);
}
cJSON_bool cJSON_IsNumber(const cJSON *const item)
cJSON_bool cJSON_IsString(const cJSON *const item)
cJSON * cJSON_Parse(const char *value)
void cJSON_Delete(cJSON *item)
const char * cJSON_GetErrorPtr(void)
cJSON * cJSON_GetObjectItem(const cJSON *const object, const char *const string)
int valueint
char * valuestring

5.2 构建并序列化 JSON

cJSON_AddStringToObject(root, "device", "sensor-01");
cJSON_AddNumberToObject(root, "temperature", 25.6);
cJSON *tags = cJSON_AddArrayToObject(root, "tags");
char *str = cJSON_PrintUnformatted(root);
/* 发送或存储 str ... */
free(str);
cJSON * cJSON_AddArrayToObject(cJSON *const object, const char *const name)
cJSON * cJSON_AddStringToObject(cJSON *const object, const char *const name, const char *const string)
cJSON * cJSON_AddNumberToObject(cJSON *const object, const char *const name, const double number)
char * cJSON_PrintUnformatted(const cJSON *item)
cJSON * cJSON_CreateString(const char *string)
cJSON * cJSON_CreateObject(void)
cJSON_bool cJSON_AddItemToArray(cJSON *array, cJSON *item)

5.3 遍历数组

cJSON *array = cJSON_GetObjectItem(root, "items");
cJSON *item;
cJSON_ArrayForEach(item, array) {
if (cJSON_IsString(item)) {
printf("%s\n", item->valuestring);
}
}
#define cJSON_ArrayForEach(element, array)

5.4 注入自定义内存分配器

cJSON_Hooks hooks = {
.malloc_fn = my_pool_alloc,
.free_fn = my_pool_free,
};
/* 后续所有 cJSON 内部分配走自定义池 */
void cJSON_InitHooks(cJSON_Hooks *hooks)

六、反模式

反模式 问题 正确做法
cJSON_Print 结果不 free 内存泄漏 用完后立即 free 或 cJSON_free
cJSON_Delete 后访问子节点指针 悬空指针 Delete 前提取所需数据
直接写 item->valueint 已标记 DEPRECATED 用 cJSON_SetNumberValue 宏
对 cJSON_PrintPreallocated 缓冲区不足 截断或失败 预留比实际多 5 字节以上
在 ISR 中调用 cJSON_Parse 内部 malloc 非中断安全 在任务上下文中调用

七、许可证

MIT License(Copyright (c) 2009-2017 Dave Gamble and cJSON contributors)。完整许可文本见 cJSON.h 文件头部。