cJSON是一个开源的跨平台的用C语言解析和生成json格式数据的库,项目地址为cJSON项目地址。使用时只需要复制 cJSON.c 和 cJSON.h 到项目中即可使用,使用示例可以参考官方的 test.c,也可以参考下面我写的示例教程。
说明:下面的代码均已验证,且不寻在内存泄漏的问题,有什么使用问题,欢迎一起交流。
#include <stdio.h>
#include <stdlib.h>
#include "cJSON.h"
int main()
{
cJSON *root = NULL, *person = NULL;
char *str_print = NULL;
/* 创建cJSON对象 */
root = cJSON_CreateObject(); /* 创建一个cJSON对象,要用 cJSON_Delete 释放内存 */
person = cJSON_CreateObject(); /* 创建子对象 */
/* 添加json节点 */
cJSON_AddItemToObject(root, "person", person);
cJSON_AddStringToObject(person, "firstName", "Lebron");
cJSON_AddStringToObject(person, "lastName", "James");
cJSON_AddNumberToObject(person, "age", 36);
cJSON_AddNumberToObject(person, "height", 206);
cJSON_AddStringToObject(root, "team", "Lakers");
/* 打印 */
str_print = cJSON_Print(root);
if(str_print != NULL)
{
printf("%s\n", str_print);
cJSON_free(str_print);
str_print = NULL;
}
/* 修改cJSON对象中的内容 */
cJSON_ReplaceItemInObject(person, "firstName", cJSON_CreateString("Chris"));
cJSON_ReplaceItemInObject(person, "lastName", cJSON_CreateString("Paul"));
cJSON_ReplaceItemInObject(person, "age", cJSON_CreateNumber(36));
cJSON_ReplaceItemInObject(person, "height", cJSON_CreateNumber(183));
cJSON_ReplaceItemInObject(root, "team", cJSON_CreateString("sun"));
/* 打印修改后的cJSON对象 */
str_print = cJSON_Print(root);
if(str_print != NULL)
{
printf("\n%s\n", str_print);
cJSON_free(str_print);
str_print = NULL;
}
/* 释放内存 */
if(root != NULL)
cJSON_Delete(root); // 防止内存泄露,会把下面所有的子节点都释放
return 0;
}
执行结果如下:
linux@linux-VirtualBox:~/myfiles/cJson$ gcc app.c cJSON.c -o app
linux@linux-VirtualBox:~/myfiles/cJson$ ./app
{
"person": {
"firstName": "Lebron",
"lastName": "James",
"age": 36,
"height": 206
},
"team": "Lakers"
}
{
"person": {
"firstName": "Chris",
"lastName": "Paul",
"age": 36,
"height": 183
},
"team": "sun"
}
将上面创建的JSON格式的数据进行解析并输出,解析代码如下。在解析代码中设置的两个数字的类型分别是整数-和小数,在打印时分别以整数和小数进行打印,发现整数打印的结果将小数取整,数值定义的是整数时小数也能打印出从结果,相应的在代码30和31行。 type为cJSON定义的数据的类型,在 cJSON.h 中的88-97行定义。
#include <stdio.h>
#include <stdlib.h>
#include "cJSON.h"
int main()
{
/* 定义要解析的JSON对象 */
char *cJSON_str = "{ \
\"person\": { \
\"firstName\": \"Lebron\", \
\"lastName\": \"James\", \
\"age\": 36, \
\"height\": 203.5 \
}, \
\"team\": \"Lakers\" \
}";
/* 解析JSON对象 */
cJSON *obj = cJSON_Parse(cJSON_str);
cJSON *child = cJSON_GetObjectItem(obj, "person"); // 从根节点下找到子节点
cJSON *firstName = cJSON_GetObjectItem(child, "firstName"); // 在子节点中找到对应的键
cJSON *lastName = cJSON_GetObjectItem(child, "lastName");
cJSON *age = cJSON_GetObjectItem(child, "age");
cJSON *height = cJSON_GetObjectItem(child, "height");
cJSON *team = cJSON_GetObjectItem(obj, "team"); // 在根节点中找到对应的键
printf("firstName type: 0x%02x, content: %s, %d\n", firstName->type, firstName->valuestring, firstName->valueint);
printf("lastName type: 0x%02x, content: %s, %f\n", lastName->type, lastName->valuestring, lastName->valuedouble);
printf("age type: 0x%02x, content: %d, %f\n", age->type, age->valueint, age->valuedouble);
printf("height type: 0x%02x, content: %d, %f\n", height->type, height->valueint, height->valuedouble);
printf("team type: 0x%02x, content: %s, %d\n", team->type, team->valuestring, team->valueint);
/* 释放空间 */
if(obj != NULL)
cJSON_Delete(obj);
return 0;
}
执行结果如下:
linux@linux-VirtualBox:~/myfiles/cJson$ gcc app.c cJSON.c -o app
linux@linux-VirtualBox:~/myfiles/cJson$ ./app
firstName type: 0x10, content: Lebron, 0
lastName type: 0x10, content: James, 0.000000
age type: 0x08, content: 36, 36.000000
height type: 0x08, content: 203, 203.500000
team type: 0x10, content: Lakers, 0
了解了简单的JSON格式数据的创建,解析后接下来讲解一下JSON数组的创建示例,代码如下:
/*
* @Description:
* @Version: 1.0
* @Autor: Crystal
* @Date: 2021-07-02 14:10:40
* @LastEditors: Crystal
* @LastEditTime: 2021-07-02 16:51:47
*/
#include <stdio.h>
#include "cJSON.h"
typedef struct{
int id;
char *name;
int age;
char *hobby;
}stu_t;
int main(void)
{
int i;
/* 定义学生信息结构体数组 */
stu_t stu_info[3] = {
{1, "xiaoming", 18, "basketball"},
{2, "xiaolan", 17, "tennis"},
{3, "xiaohong", 18, "piano"}
};
/* 创建JSON对象 */
cJSON *root = cJSON_CreateObject(); // 创建根节点
cJSON *students = cJSON_CreateObject(); // 创建 students 子节点
cJSON_AddItemToObject(root, "students", students); // 将子节点添加到根节点中
cJSON_AddNumberToObject(students, "total", 3); // 在 students 子节点添加键值对 total
cJSON *arr_info;
cJSON *stu_arr = cJSON_CreateArray(); // 创建数组
cJSON_AddItemToObject(students, "student", stu_arr); // 将数组添加到他的父节点中
for(i=0; i<sizeof(stu_info)/sizeof(stu_info[0]); ++i) // 循环给数组赋值
{
arr_info = cJSON_CreateObject(); // 创建对象
cJSON_AddNumberToObject(arr_info, "id", stu_info[i].id); // 给新创建的对象赋值
cJSON_AddStringToObject(arr_info, "name", stu_info[i].name);
cJSON_AddNumberToObject(arr_info, "age", stu_info[i].age);
cJSON_AddStringToObject(arr_info, "hobby", stu_info[i].hobby);
cJSON_AddItemToArray(stu_arr, arr_info); // 将对象添加到数组中
}
cJSON_AddStringToObject(root, "grade", "senior three"); // 将 grade 添加到他的父节点中
cJSON *subject = cJSON_CreateArray(); // 创建数组
cJSON_AddItemToObject(root, "subject", subject); // 将数组添加到他的父节点中
cJSON_AddItemToArray(subject, cJSON_CreateString("Chinese")); // 数组元素赋值
cJSON_AddItemToArray(subject, cJSON_CreateString("math"));
cJSON_AddItemToArray(subject, cJSON_CreateString("English"));
/* 格式化打印创建的带数组的JSON对象 */
char *str_print = cJSON_Print(root);
if(str_print != NULL)
{
printf("%s\n", str_print);
cJSON_free(str_print);
str_print = NULL;
}
if(root != NULL)
cJSON_Delete(root);
return 0;
}
执行结果如下:
linux@linux-VirtualBox:~/myfiles/cJson$ gcc app.c cJSON.c -o app
linux@linux-VirtualBox:~/myfiles/cJson$ ./app
{
"students": {
"total": 3,
"student": [{
"id": 1,
"name": "xiaoming",
"age": 18,
"hobby": "basketball"
}, {
"id": 2,
"name": "xiaolan",
"age": 17,
"hobby": "tennis"
}, {
"id": 3,
"name": "xiaohong",
"age": 18,
"hobby": "piano"
}]
},
"grade": "senior three",
"subject": ["Chinese", "math", "English"]
}
将上面创建的JSON格式的数据进行解析并输出,解析代码如下。
#include <stdio.h>
#include "cJSON.h"
int main(void)
{
/* 要解析的json对象 */
char *str_json = " \
{ \
\"students\" : { \
\"total\" : 3, \
\"student\" : [ \
{ \
\"id\" : 1, \
\"name\" : \"xiaoming\", \
\"age\" : 18, \
\"hobby\" : \"basketball\" \
}, \
{ \
\"id\" : 2, \
\"name\" : \"xiaolan\", \
\"age\" : 17, \
\"hobby\" : \"tennis\" \
}, \
{ \
\"id\" : 3, \
\"name\" : \"xiaohong\", \
\"age\" : 18, \
\"hobby\" : \"piano\" \
} \
] \
}, \
\"grade\" : \"senior three\", \
\"subject\": [\"Chinese\", \"math\", \"English\"] \
} \
";
cJSON *root = cJSON_Parse(str_json);
cJSON *students = cJSON_GetObjectItem(root, "students");
cJSON *total = cJSON_GetObjectItem(students, "total"); // 获取总数
cJSON *stu_arr = cJSON_GetObjectItem(students, "student"); // 获取 student 数组
int stu_arr_size = cJSON_GetArraySize(stu_arr); // 获取 student 数组中元素的个数
cJSON *grade = cJSON_GetObjectItem(root, "grade");
cJSON *subject_arr = cJSON_GetObjectItem(root, "subject"); // 获取 subject 数组
int subject_arr_size = cJSON_GetArraySize(subject_arr); // 获取 subject 数组中元素的个数
cJSON *item, *id, *name, *age, *hobby, *sub_value;
int i;
printf("total: %d\n", total->valueint);
printf("\nstu_arr_size: %d\n", stu_arr_size); // 打印 student 数组中元素的个数
for(i=0; i<stu_arr_size; ++i)
{
item = cJSON_GetArrayItem(stu_arr, i); // 获取 student 数组中的具体项
id = cJSON_GetObjectItem(item, "id");
name = cJSON_GetObjectItem(item, "name");
age = cJSON_GetObjectItem(item, "age");
hobby = cJSON_GetObjectItem(item, "hobby");
printf("id:%-1d, name:%-8s, age:%-2d, hobby:%-10s\n", id->valueint, name->valuestring, age->valueint, hobby->valuestring);
}
printf("\ngrade: %s\n", grade->valuestring);
printf("\nsubject_arr_size: %d\n", subject_arr_size); // 打印 subject 数组中元素的个数
printf("subject is: ");
for(i=0; i<subject_arr_size; ++i)
{
sub_value = cJSON_GetArrayItem(subject_arr, i);
printf("%s ", sub_value->valuestring);
}
printf("\n");
/* 释放空间 */
if(root != NULL)
{
cJSON_Delete(root);
root = NULL;
students = NULL;
total = NULL;
stu_arr = NULL;
grade = NULL;
}
return 0;
}
执行结果如下:
linux@linux-VirtualBox:~/myfiles/cJson$ gcc app.c cJSON.c -o app
linux@linux-VirtualBox:~/myfiles/cJson$ ./app
total: 3
stu_arr_size: 3
id:1, name:xiaoming, age:18, hobby:basketball
id:2, name:xiaolan , age:17, hobby:tennis
id:3, name:xiaohong, age:18, hobby:piano
grade: senior three
subject_arr_size: 3
subject is: Chinese math English