cJSON 详细教程

一、简介
cJSON 是一个使用 C 语言编写的 JSON 数据解析器,它具有超轻便、可移植和单文件的特点,采用 MIT 开源协议,cJSON 项目托管在 Github 上,仓库地址如下:[https://github.com/DaveGamble/cJSON](https://github.com/DaveGamble/cJSON)。
二、JSON 与 cJSON
1. JSON 语法规则
JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,易于人阅读和编写,同时也易于机器解析和生成,JSON 语法规则如下:
对象:无序的“名称/值”对集合,用花括号{} 包围,键值对之间用逗号, 分隔。
数组:有序的值集合,用方括号[] 包围,值之间用逗号, 分隔。
值:可以是字符串、数字、布尔值(true/false)、null、对象或数组。
字符串:用双引号" 包围。
数字:可以是整数或浮点数。
布尔值:true 或 false。
null:表示空值。
示例如下:
{
"name": "mculover666",
"age": 22,
"weight": 55.5,
"address": {
"country": "China",
"zip-code": 111111
},
"skill": ["c", "Java", "Python"],
"student": false
}2. cJSON 数据结构和设计思想
cJSON 的设计思想是通过链表来存储 JSON 数据,每个节点表示一个键值对,通过结构体cJSON 来实现,具体结构如下:
typedef struct cJSON {
struct cJSON *next;
struct cJSON *prev;
struct cJSON *child;
int type;
char *valuestring;
int valueint;
double valuedouble;
char *string;
} cJSON;next/prev:指向下一个或上一个键值对,用于遍历链表。

child:指向子节点,用于处理嵌套的 JSON 对象或数组。
type:表示值的类型(如字符串、数字等)。
valuestring:存储字符串类型的值。
valueint:存储整数值(已废弃,建议使用valuedouble)。
valuedouble:存储浮点数值。
string:存储键名。
三、JSON 数据封装
封装 JSON 数据的过程就是创建链表并向链表中添加节点的过程,以下是具体的步骤和示例代码:
1. 创建头指针和头结点
首先需要创建一个指向链表头结点的指针,并创建头结点:
cJSON *json = NULL; json = cJSON_CreateObject(); // 创建一个新的 JSON 对象
2. 向链表中添加节点
接下来可以向链表中添加各种类型的节点:
// 添加字符串
cJSON_AddStringToObject(json, "name", "mculover666");
// 添加数字
cJSON_AddNumberToObject(json, "age", 22);
// 添加布尔值
cJSON_AddBoolToObject(json, "student", cJSON_False);
// 添加数组
cJSON_AddItemToArray(json, "skills", cJSON_CreateArray());
cJSON_AddItemToArray(json->child, 0, cJSON_CreateString("c"));
cJSON_AddItemToArray(json->child, 1, cJSON_CreateString("Java"));
cJSON_AddItemToArray(json->child, 2, cJSON_CreateString("Python"));
// 添加嵌套对象
cJSON *address = cJSON_CreateObject();
cJSON_AddStringToObject(address, "country", "China");
cJSON_AddNumberToObject(address, "zip-code", 111111);
cJSON_AddItemToObject(json, "address", address);3. 打印 JSON 数据
可以使用以下函数将 JSON 数据转换为字符串并打印:
char *json_str = cJSON_Print(json);
printf("%s
", json_str);
free(json_str); // 记得释放内存四、JSON 数据解析
解析 JSON 数据就是将 JSON 字符串转换为 cJSON 结构体的过程,以下是具体的步骤和示例代码:

1. 解析 JSON 字符串
使用cJSON_Parse 函数解析 JSON 字符串:
const char *json_str = "{\"name\":\"mculover666\", \"age\":22, \"weight\":55.5, \"address\":{\"country\":\"China\",\"zip-code\":111111},\"skill\":[\"c\",\"Java\",\"Python\"],\"student\":false}";
cJSON *json = cJSON_Parse(json_str);2. 访问解析后的数据
可以通过遍历链表或其他方式访问解析后的的数据:
// 访问字符串
const char *name = cJSON_GetObjectItemCaseSensitive(json, "name")->valuestring;
printf("Name: %s
", name);
// 访问数字
double age = cJSON_GetObjectItemCaseSensitive(json, "age")->valuedouble;
printf("Age: %lf
", age);
// 访问布尔值
int is_student = cJSON_GetObjectItemCaseSensitive(json, "student")->valueint;
printf("Is student: %d
", is_student);
// 访问数组
cJSON *skills = cJSON_GetObjectItemCaseSensitive(json, "skill")->child;
while (skills) {
printf("Skill: %s
", skills->valuestring);
skills = skills->next;
}
// 访问嵌套对象
cJSON *address = cJSON_GetObjectItemCaseSensitive(json, "address");
const char *country = cJSON_GetObjectItemCaseSensitive(address, "country")->valuestring;
int zip_code = cJSON_GetObjectItemCaseSensitive(address, "zip-code")->valueint;
printf("Country: %s, ZIP Code: %d
", country, zip_code);五、内存管理
在使用 cJSON 时需要注意内存管理,及时释放不再使用的内存:
cJSON_Delete(json); // 删除整个 JSON 对象并释放内存
六、常见问题与解答
Q1:如何在 cJSON 中添加新的键值对?
A1:可以使用相应的添加函数,例如cJSON_AddStringToObject、cJSON_AddNumberToObject 等,示例如下:
cJSON_AddStringToObject(json, "new_key", "new_value");
Q2:如何从 cJSON 中删除一个键值对?
A2:可以使用cJSON_DeleteItemFromObject 函数,示例如下:
cJSON_DeleteItemFromObject(json, "new_key");
cJSON 是一个轻量级的 C 语言 JSON 解析器,通过链表结构存储 JSON 数据,支持对象的嵌套和数组的处理,使用 cJSON,可以方便地在 C 语言中进行 JSON 数据的解析和生成,在使用过程中,注意合理管理内存,避免内存泄漏。
到此,以上就是小编对于“cjson”的问题就介绍到这了,希望介绍的几点解答对大家有用,有任何问题和不懂的,欢迎各位朋友在评论区讨论,给我留言。
文章来源网络,作者:运维,如若转载,请注明出处:https://shuyeidc.com/wp/47454.html<
