如何在Arduino上使用超轻量级ANSI C JSON库cJSON:完整指南

【免费下载链接】cJSON Ultralightweight JSON parser in ANSI C 【免费下载链接】cJSON 项目地址: https://gitcode.com/gh_mirrors/cj/cJSON

cJSON是一个超轻量级的ANSI C JSON解析库,专为资源受限环境设计,非常适合在Arduino等开源硬件平台上使用。本文将详细介绍如何在Arduino项目中集成和使用cJSON库,实现JSON数据的解析与生成。

为什么选择cJSON用于Arduino开发?

cJSON库具有以下特性,使其成为Arduino项目的理想选择:

  • 超轻量级:核心代码仅有cJSON.ccJSON.h两个文件,不依赖任何外部库
  • ANSI C标准:完全使用标准C编写,兼容Arduino的AVR/ESP32等平台
  • 低内存占用:非常适合Arduino Uno等内存有限的设备
  • 易于集成:简单的API设计,学习曲线平缓
  • 开源免费:遵循MIT许可证,可自由用于商业和非商业项目

准备工作:获取cJSON库

首先需要将cJSON库添加到你的Arduino项目中:

  1. 克隆cJSON仓库到本地:

    git clone https://gitcode.com/gh_mirrors/cj/cJSON
    
  2. 从克隆的仓库中复制以下文件到你的Arduino项目文件夹:

在Arduino项目中集成cJSON

基本配置步骤

  1. 将cJSON.c和cJSON.h文件添加到Arduino IDE的项目中
  2. 在你的Arduino代码中包含cJSON头文件:
    #include "cJSON.h"
    

Arduino环境特殊配置

由于Arduino平台的特殊性,需要对cJSON进行一些调整以适应资源有限的环境:

  1. 内存管理:cJSON默认使用标准malloc/free函数,在Arduino上可以通过cJSON_InitHooks自定义内存分配函数:

    cJSON_Hooks hooks;
    hooks.malloc_fn = your_malloc_function;
    hooks.free_fn = your_free_function;
    cJSON_InitHooks(&hooks);
    
  2. 嵌套深度限制:为防止栈溢出,可调整CJSON_NESTING_LIMIT宏定义(在cJSON.h中):

    #define CJSON_NESTING_LIMIT 128  // 降低默认值以适应Arduino
    

cJSON基本用法示例

1. 解析JSON数据

以下示例展示如何解析一个简单的JSON字符串:

#include "cJSON.h"

void parseJSON() {
  const char *json = "{\"sensor\":\"temperature\",\"value\":25.5,\"unit\":\"celsius\"}";
  
  // 解析JSON字符串
  cJSON *root = cJSON_Parse(json);
  if (root == NULL) {
    const char *error_ptr = cJSON_GetErrorPtr();
    if (error_ptr != NULL) {
      Serial.print("JSON parse error: ");
      Serial.println(error_ptr);
    }
    return;
  }
  
  // 提取数据
  cJSON *sensor = cJSON_GetObjectItem(root, "sensor");
  cJSON *value = cJSON_GetObjectItem(root, "value");
  cJSON *unit = cJSON_GetObjectItem(root, "unit");
  
  if (sensor != NULL && cJSON_IsString(sensor) && 
      value != NULL && cJSON_IsNumber(value) &&
      unit != NULL && cJSON_IsString(unit)) {
    
    Serial.print("Sensor: ");
    Serial.println(sensor->valuestring);
    Serial.print("Value: ");
    Serial.println(value->valuedouble);
    Serial.print("Unit: ");
    Serial.println(unit->valuestring);
  }
  
  // 释放内存
  cJSON_Delete(root);
}

2. 生成JSON数据

以下示例展示如何创建一个JSON对象并转换为字符串:

#include "cJSON.h"

void createJSON() {
  // 创建JSON对象
  cJSON *root = cJSON_CreateObject();
  if (root == NULL) {
    Serial.println("Failed to create JSON object");
    return;
  }
  
  // 添加键值对
  cJSON_AddStringToObject(root, "status", "success");
  cJSON_AddNumberToObject(root, "timestamp", millis());
  
  // 创建数组
  cJSON *data = cJSON_CreateArray();
  cJSON_AddItemToObject(root, "data", data);
  
  // 向数组添加元素
  cJSON_AddNumberToObject(cJSON_CreateObject(), "reading", 23.4);
  cJSON_AddItemToArray(data, cJSON_CreateNumber(23.4));
  cJSON_AddItemToArray(data, cJSON_CreateNumber(24.1));
  cJSON_AddItemToArray(data, cJSON_CreateNumber(22.8));
  
  // 转换为字符串
  char *json_str = cJSON_Print(root);
  if (json_str != NULL) {
    Serial.println("Generated JSON:");
    Serial.println(json_str);
    free(json_str);  // 释放字符串内存
  }
  
  // 释放JSON对象
  cJSON_Delete(root);
}

高级应用:Arduino传感器数据的JSON封装

以下是一个完整的Arduino示例,读取DHT11传感器数据并封装为JSON格式:

#include "cJSON.h"
#include <DHT.h>

#define DHTPIN 2
#define DHTTYPE DHT11

DHT dht(DHTPIN, DHTTYPE);

void setup() {
  Serial.begin(9600);
  dht.begin();
  
  // 可选:自定义内存分配函数以优化Arduino内存使用
  cJSON_Hooks hooks;
  hooks.malloc_fn = malloc;
  hooks.free_fn = free;
  cJSON_InitHooks(&hooks);
}

void loop() {
  delay(2000);
  
  // 读取传感器数据
  float humidity = dht.readHumidity();
  float temperature = dht.readTemperature();
  
  // 检查读取是否成功
  if (isnan(humidity) || isnan(temperature)) {
    Serial.println("Failed to read from DHT sensor!");
    return;
  }
  
  // 创建JSON对象
  cJSON *root = cJSON_CreateObject();
  cJSON_AddStringToObject(root, "device", "arduino_uno");
  cJSON_AddNumberToObject(root, "timestamp", millis());
  
  // 添加传感器数据
  cJSON *sensor_data = cJSON_CreateObject();
  cJSON_AddNumberToObject(sensor_data, "temperature", temperature);
  cJSON_AddNumberToObject(sensor_data, "humidity", humidity);
  cJSON_AddItemToObject(root, "sensor_data", sensor_data);
  
  // 转换为字符串并输出
  char *json_str = cJSON_PrintUnformatted(root);
  if (json_str != NULL) {
    Serial.println(json_str);
    free(json_str);
  }
  
  // 释放内存
  cJSON_Delete(root);
}

内存优化技巧

在资源有限的Arduino设备上使用cJSON时,建议采取以下优化措施:

  1. 使用PrintUnformatted:cJSON_PrintUnformatted生成的JSON字符串更紧凑,节省内存
  2. 及时释放内存:使用完cJSON对象后立即调用cJSON_Delete释放内存
  3. 避免深层嵌套:减少JSON结构的嵌套深度,降低内存使用
  4. 预分配字符串:使用cJSON_PrintPreallocated函数减少内存分配次数
  5. 使用静态缓冲区:对于已知大小的JSON,使用静态缓冲区代替动态分配

常见问题解决

内存不足问题

如果遇到内存不足错误:

  • 尝试降低cJSON.h中的CJSON_NESTING_LIMIT值
  • 使用更精简的JSON结构
  • 确保及时释放所有cJSON对象
  • 考虑使用cJSON_PrintPreallocated代替cJSON_Print

解析错误

解析JSON时出现错误:

  • 使用cJSON_GetErrorPtr()获取错误位置
  • 检查JSON格式是否正确
  • 确保JSON字符串以null结尾
  • 验证JSON嵌套深度未超过限制

总结

cJSON库为Arduino项目提供了一个轻量级、高效的JSON处理解决方案。通过本文介绍的方法,你可以轻松地在Arduino项目中集成cJSON库,实现传感器数据的JSON格式封装与解析,为物联网应用开发打下基础。

无论是智能家居、环境监测还是工业控制项目,cJSON都能帮助你高效地处理JSON数据,让Arduino设备轻松融入现代物联网生态系统。

要了解更多cJSON的高级用法,可以参考项目中的test.c文件,其中包含了丰富的测试用例和示例代码。

【免费下载链接】cJSON Ultralightweight JSON parser in ANSI C 【免费下载链接】cJSON 项目地址: https://gitcode.com/gh_mirrors/cj/cJSON

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐