上一篇
想象一下,你正在开发一款智能温湿度传感器,需要通过MQTT协议将数据发送到云端,突然,你发现设备传输的JSON数据在服务器端解析失败——温度值莫名变成了字符串,湿度字段甚至直接消失!😱 这时候,一个可靠的JSON解析库就成了救命稻草,我们就来聊聊如何在C语言中用CJson库优雅地处理这类问题。
CJson是一个超轻量级的C语言JSON解析库,它的核心特点可以用三个词概括:
cJSON.c
和cJSON.h
两个文件,直接拖进项目就能用💡 最新版本(2025年8月)已支持JSON5标准,新增了对注释和宽松语法的解析能力!
git clone https://github.com/DaveGamble/cJSON.git # 或直接下载最新源码包:https://github.com/DaveGamble/cJSON/releases
将以下文件加入工程:
cJSON.h
(头文件)cJSON.c
(实现文件)gcc main.c cJSON.c -o sensor_app -lm
📌 注意:需要链接数学库(-lm)以支持浮点数解析
假设设备发送的JSON数据如下:
{ "device_id": "sensor_001", "temp": 25.5, "humidity": 60, "alert": false }
#include "cJSON.h" #include <stdio.h> void process_sensor_data(const char *json_str) { cJSON *root = cJSON_Parse(json_str); if (!root) { fprintf(stderr, "JSON解析失败!错误位置: %s\n", cJSON_GetErrorPtr()); return; } // 提取基础字段 double temp = cJSON_GetObjectItem(root, "temp")->valuedouble; int humidity = cJSON_GetObjectItem(root, "humidity")->valueint; int alert = cJSON_GetObjectItem(root, "alert")->valueint; printf("设备ID: %s\n", cJSON_GetObjectItem(root, "device_id")->valuestring); printf("温度: %.1f℃\n", temp); printf("湿度: %d%%\n", humidity); printf("告警: %s\n", alert ? "是" : "否"); cJSON_Delete(root); // 🔥 关键!释放内存 }
需要生成如下配置:
{ "sampling_interval": 5, "units": "metric", "alert_thresholds": { "temp_high": 35, "humidity_low": 30 } }
cJSON *create_config() { cJSON *root = cJSON_CreateObject(); // 添加基础配置 cJSON_AddNumberToObject(root, "sampling_interval", 5); cJSON_AddStringToObject(root, "units", "metric"); // 添加嵌套对象 cJSON *thresholds = cJSON_CreateObject(); cJSON_AddNumberToObject(thresholds, "temp_high", 35); cJSON_AddNumberToObject(thresholds, "humidity_low", 30); cJSON_AddItemToObject(root, "alert_thresholds", thresholds); return root; } // 使用示例 cJSON *config = create_config(); char *json_str = cJSON_PrintUnformatted(config); // 紧凑格式 printf("生成的配置:\n%s\n", json_str); free(json_str); cJSON_Delete(config);
假设收到包含历史数据的JSON:
{ "history": [ {"time": "2025-08-22T10:00:00", "temp": 24.0}, {"time": "2025-08-22T11:00:00", "temp": 25.5} ] }
cJSON *history = cJSON_GetObjectItem(root, "history"); cJSON *item; int index = 0; cJSON_ArrayForEach(item, history) { printf("记录%d:\n", ++index); printf("时间: %s\n", cJSON_GetObjectItem(item, "time")->valuestring); printf("温度: %.1f℃\n", cJSON_GetObjectItem(item, "temp")->valuedouble); }
遇到可选字段时,建议先检查类型:
cJSON *field = cJSON_GetObjectItem(root, "optional_field"); if (cJSON_IsString(field)) { printf("字符串值: %s\n", field->valuestring); } else if (cJSON_IsNumber(field)) { printf("数值: %f\n", field->valuedouble); }
症状:程序运行一段时间后崩溃,提示内存不足
解决方案:
// 正确姿势:每个cJSON_Parse都要对应cJSON_Delete cJSON *root = cJSON_Parse(json_str); // ...处理数据... cJSON_Delete(root); // 🔥 必须执行 // 生成字符串后也要释放 char *json_str = cJSON_Print(root); free(json_str); // 🔥 不要忘记
症状:cJSON_Parse
返回NULL
解决方案:
const char *error_ptr = cJSON_GetErrorPtr(); if (error_ptr != NULL) { fprintf(stderr, "错误位置: %ld\n", error_ptr - json_str); fprintf(stderr, "上下文: %.20s\n", error_ptr); }
现状:CJson本身非线程安全
解决方案:
// 方案1:线程局部存储 __thread cJSON *thread_json = NULL; // 方案2:互斥锁保护 pthread_mutex_t json_mutex = PTHREAD_MUTEX_INITIALIZER; void safe_parse(const char *json_str) { pthread_mutex_lock(&json_mutex); cJSON *root = cJSON_Parse(json_str); // ...处理... cJSON_Delete(root); pthread_mutex_unlock(&json_mutex); }
root
是否为NULLcJSON_GetObjectItemCaseSensitive
避免键名大小写问题cJSON_Print
:带缩进的格式化输出(调试用)cJSON_PrintUnformatted
:紧凑格式(传输用)cJSON_PrintPreallocated
:预分配内存的高级用法cJSON_Print
的缩进功能,节省内存你已经掌握了CJson库的核心用法!无论是处理物联网设备的实时数据流,还是构建配置管理系统,这个轻量级武器都能助你一臂之力,赶紧写段代码试试吧~ 💻
本文由 业务大全 于2025-08-22发表在【云服务器提供商】,文中图片由(业务大全)上传,本平台仅提供信息存储服务;作者观点、意见不代表本站立场,如有侵权,请联系我们删除;若有图片侵权,请您准备原始证明材料和公证书后联系我方删除!
本文链接:https://xdh.7tqx.com/wenda/690994.html
发表评论