cJSON 使用方法详解
cJSON 使用方法详解
cJSON 是一个轻量级的 C 语言 JSON 解析器和生成器库,非常适合嵌入式系统和资源受限环境。以下是 cJSON 的详细使用方法。
1. 安装与集成
下载 cJSON
可以直接从 GitHub 获取源码:
git clone https://github.com/DaveGamble/cJSON.git
集成到项目
将 cJSON.h
和 cJSON.c
复制到你的项目中,或者编译为静态库:
cd cJSON mkdir build cd build cmake .. make sudo make install # 安装到系统
2. 基本用法
创建 JSON 对象
#include <stdio.h> #include <stdlib.h> #include "cJSON.h"int main() {// 创建根对象cJSON *root = cJSON_CreateObject();// 添加基本类型cJSON_AddStringToObject(root, "name", "John Doe");cJSON_AddNumberToObject(root, "age", 30);cJSON_AddBoolToObject(root, "is_student", 0); // 0=false, 1=true// 添加数组cJSON *courses = cJSON_CreateArray();cJSON_AddItemToArray(courses, cJSON_CreateString("Math"));cJSON_AddItemToArray(courses, cJSON_CreateString("Physics"));cJSON_AddItemToObject(root, "courses", courses);// 添加嵌套对象cJSON *address = cJSON_CreateObject();cJSON_AddStringToObject(address, "city", "New York");cJSON_AddStringToObject(address, "zip", "10001");cJSON_AddItemToObject(root, "address", address);// 转换为字符串并打印char *json_str = cJSON_Print(root);printf("Generated JSON:\n%s\n", json_str);// 释放内存free(json_str);cJSON_Delete(root);return 0; }
解析 JSON 字符串
#include <stdio.h> #include <stdlib.h> #include "cJSON.h"int main() {const char *json_string = "{\"name\":\"Alice\",\"age\":25,\"is_student\":true,\"courses\":[\"Art\",\"History\"]}";// 解析JSON字符串cJSON *root = cJSON_Parse(json_string);if (root == NULL) {const char *error_ptr = cJSON_GetErrorPtr();if (error_ptr != NULL) {fprintf(stderr, "Error before: %s\n", error_ptr);}return 1;}// 获取值cJSON *name = cJSON_GetObjectItemCaseSensitive(root, "name");cJSON *age = cJSON_GetObjectItemCaseSensitive(root, "age");cJSON *is_student = cJSON_GetObjectItemCaseSensitive(root, "is_student");cJSON *courses = cJSON_GetObjectItemCaseSensitive(root, "courses");// 打印值printf("Name: %s\n", name->valuestring);printf("Age: %d\n", age->valueint);printf("Is student: %s\n", cJSON_IsTrue(is_student) ? "true" : "false");// 遍历数组printf("Courses:\n");cJSON *course = NULL;cJSON_ArrayForEach(course, courses) {printf("- %s\n", course->valuestring);}// 释放内存cJSON_Delete(root);return 0; }
3. 文件读写
写入 JSON 文件
void write_json_file(const char *filename, cJSON *json) {FILE *fp = fopen(filename, "w");if (fp == NULL) {perror("Failed to open file for writing");return;}char *json_str = cJSON_Print(json);fputs(json_str, fp);fclose(fp);free(json_str); }
读取 JSON 文件
c
cJSON *read_json_file(const char *filename) {FILE *fp = fopen(filename, "r");if (fp == NULL) {perror("Failed to open file for reading");return NULL;}// 获取文件大小fseek(fp, 0, SEEK_END);long length = ftell(fp);fseek(fp, 0, SEEK_SET);// 读取文件内容char *buffer = malloc(length + 1);if (buffer == NULL) {fclose(fp);return NULL;}fread(buffer, 1, length, fp);buffer[length] = '\0';fclose(fp);// 解析JSONcJSON *json = cJSON_Parse(buffer);free(buffer);return json; }
4. 高级用法
修改现有 JSON
void modify_json(cJSON *root) {// 修改现有值cJSON *age = cJSON_GetObjectItemCaseSensitive(root, "age");if (age != NULL) {age->valueint = 31;}// 添加新字段cJSON_AddStringToObject(root, "email", "john@example.com");// 删除字段cJSON_DeleteItemFromObject(root, "is_student"); }
错误处理
cJSON *parse_json_with_error_handling(const char *json_string) {cJSON *json = cJSON_Parse(json_string);if (json == NULL) {const char *error_ptr = cJSON_GetErrorPtr();if (error_ptr != NULL) {fprintf(stderr, "Error parsing JSON: %s\n", error_ptr);}return NULL;}return json; }
使用钩子自定义内存管理
c
// 自定义malloc/free函数 static void *custom_malloc(size_t size) {printf("Allocating %zu bytes\n", size);return malloc(size); }static void custom_free(void *ptr) {printf("Freeing memory at %p\n", ptr);free(ptr); }void use_custom_allocator() {// 设置自定义内存管理函数cJSON_Hooks hooks;hooks.malloc_fn = custom_malloc;hooks.free_fn = custom_free;cJSON_InitHooks(&hooks);// 现在cJSON会使用自定义的内存管理cJSON *root = cJSON_CreateObject();cJSON_AddStringToObject(root, "test", "value");cJSON_Delete(root); }
5. 性能优化技巧
-
使用缓冲打印:
char buffer[1024]; cJSON_PrintPreallocated(root, buffer, sizeof(buffer), 0);
-
避免频繁分配:重用 cJSON 对象
-
使用
cJSON_PrintUnformatted
节省空间:char *compact_json = cJSON_PrintUnformatted(root);
-
批量操作:减少单独的添加操作
6. 完整示例
#include <stdio.h> #include <stdlib.h> #include "cJSON.h"int main() {// 1. 创建JSONcJSON *root = cJSON_CreateObject();cJSON_AddStringToObject(root, "name", "John Smith");cJSON_AddNumberToObject(root, "age", 35);cJSON *address = cJSON_CreateObject();cJSON_AddStringToObject(address, "street", "123 Main St");cJSON_AddStringToObject(address, "city", "Boston");cJSON_AddItemToObject(root, "address", address);cJSON *phones = cJSON_CreateArray();cJSON_AddItemToArray(phones, cJSON_CreateString("555-1234"));cJSON_AddItemToArray(phones, cJSON_CreateString("555-5678"));cJSON_AddItemToObject(root, "phones", phones);// 2. 打印JSONchar *json_str = cJSON_Print(root);printf("Generated JSON:\n%s\n", json_str);free(json_str);// 3. 写入文件write_json_file("person.json", root);// 4. 从文件读取并修改cJSON *from_file = read_json_file("person.json");if (from_file != NULL) {cJSON *age = cJSON_GetObjectItemCaseSensitive(from_file, "age");age->valueint += 1;cJSON_AddBoolToObject(from_file, "married", 1);char *modified_json = cJSON_Print(from_file);printf("Modified JSON:\n%s\n", modified_json);free(modified_json);cJSON_Delete(from_file);}// 清理cJSON_Delete(root);return 0; }
7. 常见问题解决
-
内存泄漏:
-
确保为每个
cJSON_Create*
和cJSON_Print
调用相应的cJSON_Delete
和free
-
-
访问不存在的字段:
-
总是检查
cJSON_GetObjectItemCaseSensitive
的返回值是否为 NULL
-
-
类型错误:
-
使用
cJSON_IsString
,cJSON_IsNumber
等函数验证类型
-
-
大文件处理:
-
考虑流式解析或分块处理大JSON文件
-
cJSON 是一个简单但功能强大的库,适用于大多数C语言的JSON处理需求。通过合理的内存管理和错误处理,可以构建健壮的JSON处理代码。