本文详细介绍了轻量级C语言JSON解析库cJSON的使用方法,包含核心功能解析和完整代码示例

什么是cJSON?

cJSON是一个超轻量级的C语言JSON解析库,具有以下特点:

  • 单文件实现:仅需cJSON.ccJSON.h两个文件

  • 跨平台:支持所有主流操作系统和编译器

  • 简单易用:API设计简洁直观

  • 内存占用小:非常适合嵌入式系统

  • 开源免费:采用MIT许可证

环境配置

获取cJSON库

  1. 从GitHub克隆仓库:

git clone https://github.com/DaveGamble/cJSON.git
  1. 将以下文件添加到项目中:

  • cJSON.h

  • cJSON.c

包含头文件

#include "cJSON.h"

核心数据结构

cJSON使用单一结构体表示所有JSON类型:

typedef struct cJSON {
    struct cJSON *next, *prev;  // 链表指针
    struct cJSON *child;        // 子节点指针
    
    int type;                   // 数据类型
    
    char *valuestring;          // 字符串值
    int valueint;               // 整数值
    double valuedouble;         // 浮点数值
    
    char *string;               // 键名
} cJSON;

数据类型常量

常量

说明

cJSON_False

0

布尔值false

cJSON_True

1

布尔值true

cJSON_NULL

2

NULL值

cJSON_Number

3

数值类型

cJSON_String

4

字符串类型

cJSON_Array

5

数组类型

cJSON_Object

6

对象类型

cJSON_Raw

7

原始JSON(不解析)

常用API函数

创建JSON

函数

说明

cJSON_CreateObject()

创建JSON对象

cJSON_CreateArray()

创建JSON数组

cJSON_CreateString()

创建字符串类型

cJSON_CreateNumber()

创建数值类型

cJSON_CreateBool()

创建布尔类型

cJSON_CreateNull()

创建NULL类型

添加元素

函数

说明

cJSON_AddItemToObject()

向对象添加键值对

cJSON_AddItemToArray()

向数组添加元素

cJSON_AddStringToObject()

直接添加字符串键值对

cJSON_AddNumberToObject()

直接添加数值键值对

解析JSON

函数

说明

cJSON_Parse()

解析JSON字符串

cJSON_Print()

将cJSON结构转换为JSON字符串

cJSON_PrintUnformatted()

生成无格式的JSON字符串

查询数据

函数

说明

cJSON_GetObjectItem()

根据键名获取对象中的值

cJSON_GetArrayItem()

获取数组中指定索引的元素

cJSON_GetArraySize()

获取数组大小

释放内存

void cJSON_Delete(cJSON *item);

完整示例代码

创建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);
    
    // 创建嵌套对象
    cJSON *address = cJSON_CreateObject();
    cJSON_AddStringToObject(address, "street", "123 Main St");
    cJSON_AddStringToObject(address, "city", "Anytown");
    cJSON_AddItemToObject(root, "address", address);
    
    // 创建数组
    cJSON *hobbies = cJSON_CreateArray();
    cJSON_AddItemToArray(hobbies, cJSON_CreateString("reading"));
    cJSON_AddItemToArray(hobbies, cJSON_CreateString("hiking"));
    cJSON_AddItemToArray(hobbies, cJSON_CreateString("gaming"));
    cJSON_AddItemToObject(root, "hobbies", hobbies);
    
    // 生成JSON字符串
    char *json_str = cJSON_Print(root);
    printf("Created JSON:\n%s\n", json_str);
    
    // 清理内存
    cJSON_Delete(root);
    free(json_str);
    
    return 0;
}

解析JSON字符串

#include <stdio.h>
#include <stdlib.h>
#include "cJSON.h"

void parse_json(const char *json_string) {
    // 解析JSON
    cJSON *root = cJSON_Parse(json_string);
    if (!root) {
        printf("Error before: [%s]\n", cJSON_GetErrorPtr());
        return;
    }
    
    // 获取基本类型
    cJSON *name = cJSON_GetObjectItem(root, "name");
    cJSON *age = cJSON_GetObjectItem(root, "age");
    cJSON *is_student = cJSON_GetObjectItem(root, "is_student");
    
    printf("Name: %s\n", name->valuestring);
    printf("Age: %d\n", age->valueint);
    printf("Is student: %s\n", is_student->valueint ? "true" : "false");
    
    // 解析嵌套对象
    cJSON *address = cJSON_GetObjectItem(root, "address");
    cJSON *street = cJSON_GetObjectItem(address, "street");
    cJSON *city = cJSON_GetObjectItem(address, "city");
    printf("Address: %s, %s\n", street->valuestring, city->valuestring);
    
    // 解析数组
    cJSON *hobbies = cJSON_GetObjectItem(root, "hobbies");
    int hobby_count = cJSON_GetArraySize(hobbies);
    printf("Hobbies (%d):\n", hobby_count);
    
    cJSON *hobby;
    cJSON_ArrayForEach(hobby, hobbies) {
        printf("- %s\n", hobby->valuestring);
    }
    
    // 清理内存
    cJSON_Delete(root);
}

int main() {
    const char *json_string = "{"
        "\"name\": \"John Doe\","
        "\"age\": 30,"
        "\"is_student\": false,"
        "\"address\": {"
            "\"street\": \"123 Main St\","
            "\"city\": \"Anytown\""
        "},"
        "\"hobbies\": [\"reading\", \"hiking\", \"gaming\"]"
    "}";
    
    parse_json(json_string);
    return 0;
}

修改JSON数据

#include <stdio.h>
#include <stdlib.h>
#include "cJSON.h"

int main() {
    const char *json_string = "{\"name\":\"John Doe\",\"age\":30}";
    
    // 解析JSON
    cJSON *root = cJSON_Parse(json_string);
    
    // 修改现有值
    cJSON *name = cJSON_GetObjectItem(root, "name");
    cJSON_SetValuestring(name, "Jane Smith");
    
    cJSON *age = cJSON_GetObjectItem(root, "age");
    age->valueint = 32;
    
    // 添加新字段
    cJSON_AddStringToObject(root, "email", "jane@example.com");
    
    // 添加数组
    cJSON *skills = cJSON_CreateArray();
    cJSON_AddItemToArray(skills, cJSON_CreateString("C/C++"));
    cJSON_AddItemToArray(skills, cJSON_CreateString("Python"));
    cJSON_AddItemToObject(root, "skills", skills);
    
    // 输出修改后的JSON
    char *modified_json = cJSON_Print(root);
    printf("Modified JSON:\n%s\n", modified_json);
    
    // 清理内存
    cJSON_Delete(root);
    free(modified_json);
    
    return 0;
}

使用注意事项

  1. 内存管理:

    • 使用cJSON_Parse()解析的JSON需要手动调用cJSON_Delete()释放

    • cJSON_Print()生成的字符串需要手动free()

  2. 错误处理:

    • 检查cJSON_Parse()返回值是否为NULL

    • 使用cJSON_GetErrorPtr()获取错误位置

  3. 类型安全:

    • 访问数据前检查cJSON对象的type字段

    • 不要错误访问字段(如将字符串当数值访问)

  4. 性能考虑:

    • 避免在循环中频繁创建/删除小对象

    • 对于大JSON文件,考虑使用流式解析器

  5. 浮点数精度:

    • cJSON使用double存储数值

    • 注意浮点数精度问题

常见问题解答

Q:如何处理嵌套很深的JSON结构?

A:建议使用递归函数遍历JSON树。cJSON提供了childnext指针,可以遍历整个结构。

Q:cJSON支持Unicode吗?

A:cJSON本身不处理Unicode转换,需要保证输入的UTF-8编码正确。

Q:如何区分整数和浮点数?

A:cJSON将所有数值存储为double,同时提供valueint字段。可以使用cJSON_IsNumber()检查是否为数字,然后根据需求选择使用valueintvaluedouble

Q:cJSON有大小限制吗?

A:理论上只受内存限制,但极大文件可能导致解析缓慢或内存不足。

总结

cJSON是一个功能完备、轻量级的C语言JSON解析库,特别适合资源受限的环境。通过本文的学习,您应该能够:

  1. 在项目中集成cJSON库

  2. 创建和解析JSON数据

  3. 修改和操作JSON结构

  4. 避免常见的内存管理错误

  5. 处理复杂的JSON数据结构

cJSON的简洁设计使其成为C/C++项目中处理JSON数据的理想选择。无论是配置文件解析、网络通信还是数据存储,cJSON都能提供高效可靠的解决方案。

Logo

openvela 操作系统专为 AIoT 领域量身定制,以轻量化、标准兼容、安全性和高度可扩展性为核心特点。openvela 以其卓越的技术优势,已成为众多物联网设备和 AI 硬件的技术首选,涵盖了智能手表、运动手环、智能音箱、耳机、智能家居设备以及机器人等多个领域。

更多推荐