在C语言中如何制作JSON数据
在C语言中处理JSON数据(如构建、解析、序列化)是一个常见需求,尤其在嵌入式系统、后端服务或与前端交互的场景中,由于C语言本身没有内置的JSON支持,我们需要借助第三方库来实现,本文将以cJSON这一轻量级、广泛使用的开源库为例,详细介绍如何在C语言中制作JSON数据,包括环境搭建、核心API使用、实战代码示例及注意事项。
环境搭建:安装cJSON库
cJSON是一个用C语言编写的JSON解析器/生成器,具有轻量(仅两个文件:cJSON.h和cJSON.c)、无依赖、跨平台的特点,适合C语言项目。
获取源码
- 从GitHub仓库下载最新版本:
https://github.com/DaveGamble/cJSON.git
或直接下载单个文件:cJSON.h(头文件)和cJSON.c(源文件)。
集成到项目
将cJSON.h和cJSON.c添加到你的C语言项目中,如果是命令行编译,链接时需包含cJSON.c:
gcc your_program.c cJSON.c -o your_program -lm
(-lm是链接数学库,部分版本可能需要)
cJSON核心概念:JSON与cJSON对象的映射
JSON数据本质上是“键值对”的嵌套结构,cJSON通过cJSON对象(对应JSON对象/字典)和cJSON数组(对应JSON数组)来表示,常见类型映射如下:
| JSON类型 | cJSON类型 | 说明 |
|---|---|---|
| 对象 | cJSON*(对象) |
通过cJSON_CreateObject()创建 |
数组 [] |
cJSON*(数组) |
通过cJSON_CreateArray()创建 |
| 字符串 | cJSON*(字符串) |
通过cJSON_CreateString()创建 |
| 数字(整数/浮点) | cJSON*(数字/浮点数) |
通过cJSON_CreateNumber()创建 |
布尔值 true/false |
cJSON*(布尔) |
通过cJSON_CreateTrue()/cJSON_CreateFalse()创建 |
| null | cJSON*(null) |
通过cJSON_CreateNull()创建 |
实战:分步制作JSON数据
假设我们要构建以下JSON对象(用户信息):
{
"name": "张三",
"age": 25,
"isStudent": false,
"courses": ["数学", "英语", "编程"],
"address": {
"city": "北京",
"district": "海淀区"
},
"score": 85.5
}
步骤1:包含头文件并创建根对象
#include <stdio.h>
#include <stdlib.h>
#include "cJSON.h"
int main() {
// 1. 创建JSON对象(作为根节点)
cJSON *root = cJSON_CreateObject();
if (!root) {
printf("创建JSON对象失败!\n");
return -1;
}
// 后续操作中,所有cJSON对象都通过root递归构建
}
步骤2:添加键值对(字符串、数字、布尔值)
- 添加字符串:
name->"张三"cJSON_AddStringToObject(root, "name", "张三");
- 添加整数:
age->25cJSON_AddNumberToObject(root, "age", 25);
- 添加布尔值:
isStudent->falsecJSON_AddBoolToObject(root, "isStudent", cJSON_False);
步骤3:添加数组(courses)
- 创建数组对象:
cJSON *courses = cJSON_CreateArray(); if (!courses) { printf("创建数组失败!\n"); cJSON_Delete(root); return -1; } - 向数组中添加字符串元素:
cJSON_AddItemToArray(courses, cJSON_CreateString("数学")); cJSON_AddItemToArray(courses, cJSON_CreateString("英语")); cJSON_AddItemToArray(courses, cJSON_CreateString("编程")); - 将数组添加到根对象:
cJSON_AddItemToObject(root, "courses", courses);
步骤4:添加嵌套对象(address)
- 创建嵌套对象:
cJSON *address = cJSON_CreateObject(); if (!address) { printf("创建嵌套对象失败!\n"); cJSON_Delete(root); return -1; } - 添加嵌套键值对:
cJSON_AddStringToObject(address, "city", "北京"); cJSON_AddStringToObject(address, "district", "海淀区");
- 将嵌套对象添加到根对象:
cJSON_AddItemToObject(root, "address", address);
步骤5:添加浮点数(score)
cJSON_AddNumberToObject(root, "score", 85.5);
步骤6:序列化JSON为字符串
构建完成后,需要将cJSON对象转换为字符串格式,以便存储或传输:
char *json_str = cJSON_Print(root);
if (json_str) {
printf("生成的JSON字符串:\n%s\n", json_str);
free(json_str); // 注意:cJSON_Print返回的字符串需要手动释放
}
步骤7:释放内存
cJSON对象是动态分配的,使用后必须手动释放,避免内存泄漏:
cJSON_Delete(root); // 递归释放所有子对象
完整代码
#include <stdio.h>
#include <stdlib.h>
#include "cJSON.h"
int main() {
// 1. 创建根对象
cJSON *root = cJSON_CreateObject();
if (!root) {
printf("创建JSON对象失败!\n");
return -1;
}
// 2. 添加基本键值对
cJSON_AddStringToObject(root, "name", "张三");
cJSON_AddNumberToObject(root, "age", 25);
cJSON_AddBoolToObject(root, "isStudent", cJSON_False);
// 3. 添加数组(courses)
cJSON *courses = cJSON_CreateArray();
cJSON_AddItemToArray(courses, cJSON_CreateString("数学"));
cJSON_AddItemToArray(courses, cJSON_CreateString("英语"));
cJSON_AddItemToArray(courses, cJSON_CreateString("编程"));
cJSON_AddItemToObject(root, "courses", courses);
// 4. 添加嵌套对象(address)
cJSON *address = cJSON_CreateObject();
cJSON_AddStringToObject(address, "city", "北京");
cJSON_AddStringToObject(address, "district", "海淀区");
cJSON_AddItemToObject(root, "address", address);
// 5. 添加浮点数
cJSON_AddNumberToObject(root, "score", 85.5);
// 6. 序列化为字符串
char *json_str = cJSON_Print(root);
if (json_str) {
printf("生成的JSON字符串:\n%s\n", json_str);
free(json_str);
}
// 7. 释放内存
cJSON_Delete(root);
return 0;
}
输出结果
{
"name": "张三",
"age": 25,
"isStudent": false,
"courses": [ "数学", "英语", "编程" ],
"address": {
"city": "北京",
"district": "海淀区"
},
"score": 85.5
}
进阶操作:格式化与错误处理
格式化输出(缩进美化)
默认的cJSON_Print输出无缩进,可使用cJSON_PrintPreallocated(需预分配缓冲区)或cJSON_PrintBuffered(自动管理缓冲区)实现格式化:
char *formatted_json = cJSON_Print(root);
if (formatted_json) {
printf("格式化后的JSON:\n%s\n", formatted_json);
free(formatted_json);
}
错误处理
cJSON通过cJSON_GetErrorPtr()获取错误位置(需开启CJSON_TRACK_ERROR_POINTER宏):
// 在cJSON.h中定义:#define CJSON_TRACK_ERROR_POINTER 1
cJSON *item = cJSON_Parse("invalid json");
if (!item) {
printf("JSON解析失败:%s\n", cJSON_GetErrorPtr());
}
修改JSON数据
- 修改键值:直接调用
cJSON_AddXXXToObject覆盖同名键:



还没有评论,来说两句吧...