1. JSON 是什么?
JSON(JavaScript Object Notation)是一种轻量级文本数据格式,常用于网络传输和配置文件保存。
在物联网中,设备经常把传感器数据组织为 JSON,再通过 MQTT、HTTP 等协议上传,例如:
{
"temp": 25.5,
"humidity": 60
}
JSON 是纯文本,易读、跨语言,C、Python、JavaScript 等都可以处理。
2. JSON 的两种结构
对象:键值对集合
对象使用 {},键必须是双引号包围的字符串,键和值用 : 分隔:
{
"name": "sensor-01",
"online": true
}
数组:有序值集合
数组使用 [],元素用逗号分隔:
["json", "mqtt", "rt-thread"]
对象和数组可以互相嵌套,用于表达复杂数据。
3. JSON 支持的值类型
| 类型 | 示例 | 注意 |
|---|---|---|
| 字符串 | "hello" |
必须使用双引号。 |
| 数值 | 42、3.14 |
不加引号。 |
| 布尔值 | true、false |
必须小写。 |
| 空值 | null |
表示无值。 |
| 数组 | [1, 2, 3] |
有序集合。 |
| 对象 | {"id": 1} |
键值对集合。 |
4. JSON 语法要点
-
键必须是双引号包围的字符串,不能写成
{name: "tom"}。 -
最后一个成员后面不能有逗号。
-
字符串中需要转义时使用
\"、\\、\n等。 -
空格和换行不影响 JSON 含义,可用于提升可读性。
-
JSON 不是 C 结构体,也不能写注释。
错误示例:
{
"temp": 25.5,
}
最后多出的逗号会导致 JSON 解析失败。
5. RT-Thread 中使用 cJSON
cJSON 是一个常用的 C 语言 JSON 库。RT-Thread 已将其制作为软件包,启用后包含头文件即可使用:
#include <cJSON.h>
cJSON 的核心操作:
解析:cJSON_Parse() → 读取字段 → cJSON_Delete()
编码:创建对象 → 添加字段 → cJSON_Print() → 释放字符串和对象
6. cJSON 解析示例
const char *json_text =
"{\"temp\":25.5,\"humidity\":60,\"online\":true}";
cJSON *root = cJSON_Parse(json_text);
if (root != RT_NULL)
{
cJSON *temp = cJSON_GetObjectItemCaseSensitive(root, "temp");
cJSON *online = cJSON_GetObjectItemCaseSensitive(root, "online");
if (cJSON_IsNumber(temp) && cJSON_IsBool(online))
{
rt_kprintf("temp: %.1f, online: %d\n",
temp->valuedouble,
cJSON_IsTrue(online));
}
cJSON_Delete(root);
}
代码解析: cJSON_Parse() 将 JSON 文本转换为内存中的 JSON 树,失败时返回 RT_NULL。cJSON_GetObjectItemCaseSensitive() 按键名获取字段;在访问 valuedouble 前,通过 cJSON_IsNumber() 检查类型,避免字段缺失或类型不匹配导致异常。最后的 cJSON_Delete(root) 必须执行,用于释放整棵 JSON 树。
7. cJSON 编码示例
cJSON *root = cJSON_CreateObject();
if (root != RT_NULL)
{
cJSON_AddNumberToObject(root, "temp", 25.5);
cJSON_AddNumberToObject(root, "humidity", 60);
cJSON_AddBoolToObject(root, "online", 1);
char *json_str = cJSON_PrintUnformatted(root);
if (json_str != RT_NULL)
{
rt_kprintf("%s\n", json_str);
cJSON_free(json_str);
}
cJSON_Delete(root);
}
代码解析: cJSON_CreateObject() 创建根对象,随后将温度、湿度和在线状态作为键值对加入。cJSON_PrintUnformatted() 生成紧凑 JSON 字符串,适合 MQTT 等网络传输。该字符串由 cJSON 分配,使用后必须调用 cJSON_free();根对象则通过 cJSON_Delete() 释放。两种资源不能混用普通 free() 或遗漏释放。
8. 嵌套对象与数组
{
"device": {
"id": "sensor-01",
"status": "online"
},
"values": [25.5, 60]
}
读取嵌套数据时,先获取外层对象,再获取内层字段;读取数组时可以用 cJSON_GetArraySize() 获取长度,用 cJSON_GetArrayItem() 按下标访问。
总结
JSON 用对象和数组组织文本数据;cJSON 则帮助 C 语言完成 JSON 的解析与生成。
接收 JSON:Parse → 校验字段 → 使用数据 → Delete
发送 JSON:Create → Add → Print → free 字符串 → Delete 对象
掌握这条流程后,就可以将 JSON 与 MQTT 结合,用于 RT-Thread 设备的数据上报和指令解析。