cJSON使用

cJSON使用

1.简介

json是一个轻量级的数据存储交换语言,其是通过键值对的形式存储的,例如:{ "key" : "value" }

键需要使用双括号括起来,值如果是字符串也需要使用双引号括起来。

2.cJSON介绍

cJSON 是轻量级的 C 语言 JSON 解析 / 构建库,核心围绕 cJSON 结构体展开

1.格式

cpp 复制代码
{
    "name": "小明",
    "age": 53,
    "interest": {
        "basketball": "篮球",
        "badminton": "羽毛球"
    },
    "color": [
        "black",
        "white"
    ],
    "like": [
        {
            "game": "马里奥",
            "price": 47.8
        },
        {
            "game": "魂斗罗",
            "price": 88
        }
    ],
    "vip": true,
    "address": null
}

2.结构体

cpp 复制代码
typedef struct cJSON {
	struct cJSON *next,*prev;	/* next是获取下一个元素数据,prev是获取前一个元素数据 */
	struct cJSON *child;		/* 获取第一个元素数据,当需要获取下一个时,就得使用next了. */

	int type;					/* 当前的json类型对象、数组、字符串、数字、null、true、false等 */

	char *valuestring;			/* 字符串值, if type==cJSON_String */
	int valueint;				/* 整形类型值, if type==cJSON_Number */
	double valuedouble;			/* 浮点数类型值, if type==cJSON_Number */

	char *string;				/* 这个是键 */
} cJSON;

type:

type类型通过下面定义的宏进行判断:

cpp 复制代码
#define cJSON_False 0		// true
#define cJSON_True 1		// false
#define cJSON_NULL 2		// NULL
#define cJSON_Number 3		// 数字
#define cJSON_String 4		// 字符串
#define cJSON_Array 5		// 数组
#define cJSON_Object 6		// 对象

3.常用cJSON函数

1.解析类(JSON字符串->cJSON对象)

将JSON格式字符串解析为cJSON(根节点),是读取JSON的入口。

解析 JSON 字符串为 cJSON 根节点

c 复制代码
cJSON *cJSON_Parse(const char *value);
  • 参数:value = 待解析的 JSON 字符串
  • 返回:成功返回根节点指针,失败返回 NULL

获取解析失败的位置

c 复制代码
const char *cJSON_GetErrorPtr(void);
  • 解析失败时调用,返回错误位置的字符串指针
    示例:
c 复制代码
const char *json_str = "{\"name\":\"Tom\",\"age\":20}";
cJSON *root = cJSON_Parse(json_str);
if (root == NULL) {
    printf("解析失败:%s\n", cJSON_GetErrorPtr()); // 打印错误位置
    return -1;
}

2. 打印类(cJSON 对象 → JSON 字符串)

将 cJSON 结构体转换为字符串,用于输出 / 存储 JSON。

转换为格式化 JSON 字符串(带缩进、换行,易读)

c 复制代码
char *cJSON_Print(const cJSON *item);
  • 返回的字符串需手动 free() 释放

换为紧凑格式 JSON 字符串(无空格 / 换行)

c 复制代码
char *cJSON_PrintUnformatted(const cJSON *item);
  • 同上,适合网络传输 / 存储
    示例:
c 复制代码
char *fmt_str = cJSON_Print(root);   // 格式化输出
char *compact_str = cJSON_PrintUnformatted(root); // 紧凑输出
printf("格式化JSON:\n%s\n", fmt_str);
free(fmt_str);       // 必须释放
free(compact_str);

3.创建类(构建 JSON 对象 / 数组)

手动构建 JSON 节点(对象、数组、字符串、数字等),是生成 JSON 的核心。

创建空 JSON 对象

c 复制代码
cJSON *cJSON_CreateObject(void);
//示例
cJSON *obj = cJSON_CreateObject();

创建空 JSON 数组

c 复制代码
cJSON *cJSON_CreateArray(void);
//示例
cJSON *arr = cJSON_CreateArray();

**创建字符串节点 **

c 复制代码
cJSON *cJSON_CreateString(const char *s);
//示例
cJSON *str_node = cJSON_CreateString("Tom");

创建数字节点(整数 / 浮点通用)

c 复制代码
cJSON *cJSON_CreateNumber(double num);
//示例
cJSON *num_node = cJSON_CreateNumber(20.5);

**创建布尔节点 **

c 复制代码
cJSON *cJSON_CreateBool(cJSON_bool b);
//示例
cJSON *bool_node = cJSON_CreateBool(1); // true

**向对象添加键值对 **

c 复制代码
cJSON_AddItemToObject(cJSON *obj, const char *key, cJSON *item);
//示例
cJSON_AddItemToObject(obj, "name", str_node);

**向数组添加节点 **

c 复制代码
cJSON_AddItemToArray(cJSON *arr, cJSON *item);
//示例
cJSON_AddItemToArray(arr, num_node);

**一键添加键值对(无需手动创建节点) **

c 复制代码
cJSON_AddStringToObject(obj, "name", "Tom");
cJSON_AddNumberToObject(obj, "age", 20);
cJSON_AddBoolToObject(obj, "is_student", 1);

示例(构建 JSON)

c 复制代码
// 创建对象
cJSON *new_obj = cJSON_CreateObject();
// 一键添加键值对(简化宏)
cJSON_AddStringToObject(new_obj, "name", "Jerry");
cJSON_AddNumberToObject(new_obj, "age", 18);
// 创建数组并添加到对象
cJSON *hobbies = cJSON_CreateArray();
cJSON_AddItemToArray(hobbies, cJSON_CreateString("reading"));
cJSON_AddItemToObject(new_obj, "hobbies", hobbies);

4.获取类(从 JSON 中取值)

从解析后的 cJSON 对象 / 数组中提取指定值,需先判断节点类型避免出错。

大小写敏感获取对象的 key 节点(推荐)

c 复制代码
cJSON *cJSON_GetObjectItemCaseSensitive(const cJSON *obj, const char *key);
//示例
cJSON *name = cJSON_GetObjectItemCaseSensitive(root, "name");

大小写不敏感获取 key 节点(不推荐)

c 复制代码
cJSON *cJSON_GetObjectItem(const cJSON *obj, const char *key);
//示例
cJSON *name = cJSON_GetObjectItemCaseSensitive(root, "name");

获取数组长度

c 复制代码
int cJSON_GetArraySize(const cJSON *arr);
//示例
int size = cJSON_GetArraySize(scores_arr);

获取数组指定索引的节点(idx 从 0 开始)

c 复制代码
cJSON *cJSON_GetArrayItem(const cJSON *arr, int idx);
//示例
cJSON *score = cJSON_GetArrayItem(scores_arr, 0);

示例

c 复制代码
// 1. 提取字符串(先判断是否为字符串类型)
cJSON *name = cJSON_GetObjectItemCaseSensitive(root, "name");
if (cJSON_IsString(name) && name->valuestring) {
    printf("name: %s\n", name->valuestring);
}

// 2. 提取整数/浮点(先判断是否为数字类型)
cJSON *age = cJSON_GetObjectItemCaseSensitive(root, "age");
if (cJSON_IsNumber(age)) {
    printf("age(int): %d\n", age->valueint);    // 整数
    printf("age(double): %.1f\n", age->valuedouble); // 浮点
}

// 3. 提取布尔(判断布尔类型)
cJSON *is_stu = cJSON_GetObjectItemCaseSensitive(root, "is_student");
if (cJSON_IsBool(is_stu)) {
    printf("is_student: %s\n", cJSON_IsTrue(is_stu) ? "true" : "false");
}

// 4. 遍历数组
cJSON *scores = cJSON_GetObjectItemCaseSensitive(root, "scores");
if (cJSON_IsArray(scores)) {
    int size = cJSON_GetArraySize(scores);
    for (int i = 0; i < size; i++) {
        cJSON *s = cJSON_GetArrayItem(scores, i);
        if (cJSON_IsNumber(s)) {
            printf("score[%d]: %.1f\n", i, s->valuedouble);
        }
    }
}

5. 修改 / 替换类

修改已存在的 JSON 节点(替换值、新增节点等)。

替换对象中指定 key 的节点

c 复制代码
void cJSON_ReplaceItemInObject(cJSON *obj, const char *key, cJSON *new_item);

向对象添加节点引用(不复制内存,仅引用)

c 复制代码
void cJSON_AddItemReferenceToObject(cJSON *obj, const char *key, cJSON *item);

示例:

c 复制代码
// 替换 age 的值
cJSON *new_age = cJSON_CreateNumber(21);
cJSON_ReplaceItemInObject(root, "age", new_age);

6. 释放类(内存管理,必用!)

cJSON 是手动内存管理,解析 / 创建的节点必须释放,否则内存泄漏。

递归释放节点及其所有子节点

c 复制代码
void cJSON_Delete(cJSON *node);
  • 只需释放根节点,子节点会被递归释放

7.类型判断宏(辅助,避免出错)

取值前必须判断节点类型,否则可能访问空指针 / 错误成员:

c 复制代码
cJSON_IsNull(item)      // 是否为 NULL 类型
cJSON_IsTrue(item)      // 是否为 true
cJSON_IsFalse(item)     // 是否为 false
cJSON_IsBool(item)      // 是否为布尔类型
cJSON_IsNumber(item)    // 是否为数字类型
cJSON_IsString(item)    // 是否为字符串类型
cJSON_IsArray(item)     // 是否为数组类型
cJSON_IsObject(item)    // 是否为对象类型

4.综合示例(解析 + 创建 + 取值 + 释放)

c 复制代码
#include <stdio.h>
#include <stdlib.h>
#include "cJSON.h"

int main(){
    // 1.解析JSON字符串
    const char *json_str = "{\"name\":\"Tom\",\"age\":20,\"is_student\":true,\"scores\":[90.5, 85, 95]}";
    cJSON *root = cJSON_Parse(json_str);
    if (root == NULL) {
        printf("解析失败:%s\n", cJSON_GetErrorPtr());
        return -1;
    }

    // 2.提取数据
        //提取字符串
    cJSON *name = cJSON_GetObjectItemCaseSensitive(root, "name");
    if (cJSON_IsString(name) && name->valuestring) {
        printf("name: %s\n", name->valuestring);
    }
        //提取数字
    cJSON *age = cJSON_GetObjectItemCaseSensitive(root, "age");
    if (cJSON_IsNumber(age)) {
        printf("age(int): %d\n", age->valueint);    // 整数
        printf("age(double): %.1f\n", age->valuedouble); // 浮点
    }
    
    // 3.创建新JSON
    cJSON *new_obj = cJSON_CreateObject();
    cJSON_AddStringToObject(new_obj, "name", "Jerry");
    cJSON_AddNumberToObject(new_obj, "age", 18);
    cJSON *hobbies = cJSON_CreateArray();
    cJSON_AddItemToArray(hobbies, cJSON_CreateString("reading"));
    cJSON_AddItemToObject(new_obj, "hobbies", hobbies);

    // 4.打印新JSON字符串
    char *fmt_str = cJSON_Print(new_obj);
    printf("\n新JSON:\n%s\n", fmt_str);

    // 5. 修改
    cJSON_ReplaceItemInObject(new_obj, "age", cJSON_CreateNumber(25));
    char *fmt_str2 = cJSON_Print(new_obj);
    printf("\n修改后JSON:\n%s\n", fmt_str2);

    //5.释放内存
    cJSON_Delete(root);
    cJSON_Delete(new_obj);
    free(fmt_str);
    free(fmt_str2);
    return 0;

}
相关推荐
正在走向自律19 小时前
从Oracle到金仓KES:PL/SQL兼容性与高级JSON处理实战解析
数据库·sql·oracle·json·金仓数据库·电科金仓·兼容性挑战
皮卡龙1 天前
Java常用的JSON
java·开发语言·spring boot·json
@#---1 天前
如何准确判断json文件并且拿到我想要的信息
android·python·json
WarPigs2 天前
Unity添加Newtonsoft.json
json
张彦峰ZYF2 天前
巨大 JSON / 图结构数据架构层面选型:该放 Redis 还是 MongoDB?
redis·架构·json·巨大json/图结构架构选型·redis-mongodb
一颗不甘坠落的流星2 天前
【Antd】基于 Upload 组件,导入Json文件并转换为Json数据
前端·javascript·json
亮子AI2 天前
application/json 服务器收到的是字符串,还是json对象?
运维·服务器·json
im_AMBER3 天前
weather-app开发手记 02 JSON基础 | API 调用 400 错误修复 | JWT 认证问题
笔记·学习·json·axios·jwt
Irene19913 天前
Prettier 配置文件 .prettierrc.js 和 .prettierrc.json 的区别
javascript·json