JSON 与 cJSON 学习笔记

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 设备的数据上报和指令解析。

相关推荐
咖啡忍者33 分钟前
【SAP BASIS】Section 5: SAP System Configuration
笔记
UIU1146 小时前
递归算法与汉诺塔
c++·学习·算法·c#·递归
一隅论数智6 天前
给AI一张“业务概念地图“:本体如何从哲学走向企业智能
大数据·人工智能·经验分享·笔记·学习·学习方法·政务
XiHongShi20166 天前
STM32F407 RTC定时器例程,建议保存
stm32·单片机·学习
譕痕6 天前
JSONObject与JSONArray封装数据格式区别
java·json
A黄俊辉A6 天前
uniapp webview中实现 app和内嵌的H5双向通信
vue.js·json
爱吃苹果的日记本6 天前
离散数学第六课
学习·离散数学
AI职业加油站6 天前
AI智能体应用工程师证书:政策红利下的职业新风口
大数据·运维·人工智能·学习·职场发展
深圳老胡6 天前
STM32F407 控制 L6470 步进电机驱动 —— 控制过程简介
笔记·stm32·单片机·嵌入式硬件·代码规范