cJSON 是一个用 C 语言编写的轻量级 JSON 解析库,旨在提供简单、高效的方式来处理 JSON 数据。它适用于需要解析或生成 JSON 数据的各种应用场景,尤其是资源受限的嵌入式系统或对性能有较高要求的项目。
https://github.com/DaveGamble/cJSON/releases
typedef struct cJSON { /* next/prev 允许您遍历数组/对象链。也可以使用 GetArraySize/GetArrayItem/GetObjectItem */ struct cJSON *next; struct cJSON *prev; /* 数组或对象项将有一个 child 指针,指向数组/对象中项目的链 */ struct cJSON *child; /* 项目的类型,如上所述 */ int type; /* 如果 type == cJSON_String 或 type == cJSON_Raw,则为项目的字符串值 */ char *valuestring; /* 写入 valueint 已被弃用,请使用 cJSON_SetNumberValue 代替 */ int valueint; /* 如果 type == cJSON_Number,则为项目的数字值 */ double valuedouble; /* 如果该项目是对象的孩子,或者在对象子项列表中,则为项目的名称字符串 */ char *string; } cJSON;
这里直接贴出我封装好的cjson库文件
json_wrapper.h
#ifndef JSON_WRAPPER_H
#define JSON_WRAPPER_H
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include "cJSON.h"
// ====================
// 类型定义
// ====================
typedef struct JsonObject JsonObject;
typedef struct JsonArray JsonArray;
// ====================
// 内存管理
// ====================
void json_free(void *json);
// ====================
// JSON 对象操作
// ====================
JsonObject *json_object_create();
JsonObject *json_object_parse(const char *json_str);
char *json_object_to_string(JsonObject *obj, bool formatted);
bool json_object_save_to_file(JsonObject *obj, const char *filename);
void json_object_put_string(JsonObject *obj, const char *key, const char *value);
void json_object_put_number(JsonObject *obj, const char *key, double value);
void json_object_put_bool(JsonObject *obj, const char *key, bool value);
void json_object_put_null(JsonObject *obj, const char *key);
void json_object_put_object(JsonObject *obj, const char *key, JsonObject *value);
void json_object_put_array(JsonObject *obj, const char *key, JsonArray *value);
const char *json_object_get_string(JsonObject *obj, const char *key, const char *default_value);
double json_object_get_number(JsonObject *obj, const char *key, double default_value);
bool json_object_get_bool(JsonObject *obj, const char *key, bool default_value);
JsonObject *json_object_get_object(JsonObject *obj, const char *key);
JsonArray *json_object_get_array(JsonObject *obj, const char *key);
// ====================
// JSON 数组操作
// ====================
JsonArray *json_array_create();
JsonArray *json_array_parse(const char *json_str);
int json_array_size(JsonArray *array);
void json_array_append_string(JsonArray *array, const char *value);
void json_array_append_number(JsonArray *array, double value);
void json_array_append_bool(JsonArray *array, bool value);
void json_array_append_null(JsonArray *array);
void json_array_append_object(JsonArray *array, JsonObject *value);
void json_array_append_array(JsonArray *array, JsonArray *value);
const char *json_array_get_string(JsonArray *array, int index, const char *default_value);
double json_array_get_number(JsonArray *array, int index, double default_value);
bool json_array_get_bool(JsonArray *array, int index, bool default_value);
JsonObject *json_array_get_object(JsonArray *array, int index);
JsonArray *json_array_get_array(JsonArray *array, int index);
#endif // JSON_WRAPPER_H
json_wrapper.c
#include "json_wrapper.h"
#include <string.h>
// ====================
// 内部结构定义
// ====================
/**
* @struct JsonObject
* @brief 封装cJSON对象的结构体
*
* @param cjson 指向底层cJSON对象的指针
* @param auto_free 标记是否在释放时自动删除底层cJSON对象
*/
struct JsonObject
{
cJSON *cjson;
bool auto_free;
};
/**
* @struct JsonArray
* @brief 封装cJSON数组的结构体
*
* @param cjson 指向底层cJSON数组的指针
* @param auto_free 标记是否在释放时自动删除底层cJSON数组
*/
struct JsonArray
{
cJSON *cjson;
bool auto_free;
};
// ====================
// 内存管理
// ====================
/**
* @brief 释放JSON对象或数组占用的内存
*
* @param json 要释放的JsonObject或JsonArray指针
*
* 注意:如果auto_free为true,会同时释放底层的cJSON结构
*/
void json_free(void *json)
{
if (!json)
return;
if (((JsonObject *)json)->auto_free)
{
cJSON_Delete(((JsonObject *)json)->cjson);
}
free(json);
}
// ====================
// 内部辅助函数
// ====================
/**
* @brief 创建JsonObject结构
*
* @param cjson 底层cJSON对象
* @param auto_free 是否自动管理内存
* @return JsonObject* 创建的对象指针,失败返回NULL
*/
static JsonObject *create_json_object(cJSON *cjson, bool auto_free)
{
if (!cjson)
return NULL;
JsonObject *obj = malloc(sizeof(JsonObject));
if (!obj)
return NULL;
obj->cjson = cjson;
obj->auto_free = auto_free;
return obj;
}
/**
* @brief 创建JsonArray结构
*
* @param cjson 底层cJSON数组
* @param auto_free 是否自动管理内存
* @return JsonArray* 创建的数组指针,失败返回NULL
*/
static JsonArray *create_json_array(cJSON *cjson, bool auto_free)
{
if (!cjson)
return NULL;
JsonArray *array = malloc(sizeof(JsonArray));
if (!array)
return NULL;
array->cjson = cjson;
array->auto_free = auto_free;
return array;
}
// ====================
// JSON 对象操作实现
// ====================
/**
* @brief 创建一个空的JSON对象
*
* @return JsonObject* 新创建的JSON对象
*/
JsonObject *json_object_create()
{
return create_json_object(cJSON_CreateObject(), true);
}
/**
* @brief 从JSON字符串解析创建JSON对象
*
* @param json_str JSON格式的字符串
* @return JsonObject* 解析后的JSON对象,失败返回NULL
*/
JsonObject *json_object_parse(const char *json_str)
{
cJSON *cjson = cJSON_Parse(json_str);
if (!cjson)
return NULL;
return create_json_object(cjson, true);
}
/**
* @brief 将JSON对象序列化为字符串
*
* @param obj 要序列化的JSON对象
* @param formatted 是否格式化输出(带缩进)
* @return char* 序列化后的字符串,需调用free释放
*/
char *json_object_to_string(JsonObject *obj, bool formatted)
{
if (!obj || !obj->cjson)
return NULL;
return formatted ? cJSON_Print(obj->cjson) : cJSON_PrintUnformatted(obj->cjson);
}
/**
* @brief 将JSON对象保存到文件
*
* @param obj 要保存的JSON对象
* @param filename 目标文件名
* @return true 保存成功
* @return false 保存失败
*/
bool json_object_save_to_file(JsonObject *obj, const char *filename)
{
if (!obj || !obj->cjson || !filename)
return false;
char *json_str = cJSON_Print(obj->cjson);
if (!json_str)
return false;
FILE *fp = fopen(filename, "w");
if (!fp)
{
free(json_str);
return false;
}
fputs(json_str, fp);
fclose(fp);
free(json_str);
return true;
}
/**
* @brief 向JSON对象添加字符串属性
*
* @param obj JSON对象
* @param key 属性键
* @param value 字符串值
*/
void json_object_put_string(JsonObject *obj, const char *key, const char *value)
{
if (obj && obj->cjson && key)
{
cJSON_AddStringToObject(obj->cjson, key, value);
}
}
/**
* @brief 向JSON对象添加数值属性
*
* @param obj JSON对象
* @param key 属性键
* @param value 数值
*/
void json_object_put_number(JsonObject *obj, const char *key, double value)
{
if (obj && obj->cjson && key)
{
cJSON_AddNumberToObject(obj->cjson, key, value);
}
}
/**
* @brief 向JSON对象添加布尔属性
*
* @param obj JSON对象
* @param key 属性键
* @param value 布尔值
*/
void json_object_put_bool(JsonObject *obj, const char *key, bool value)
{
if (obj && obj->cjson && key)
{
cJSON_AddBoolToObject(obj->cjson, key, value);
}
}
/**
* @brief 向JSON对象添加null属性
*
* @param obj JSON对象
* @param key 属性键
*/
void json_object_put_null(JsonObject *obj, const char *key)
{
if (obj && obj->cjson && key)
{
cJSON_AddNullToObject(obj->cjson, key);
}
}
/**
* @brief 向JSON对象添加子对象
*
* @param obj JSON对象
* @param key 属性键
* @param value 子对象(所有权转移给父对象)
*/
void json_object_put_object(JsonObject *obj, const char *key, JsonObject *value)
{
if (obj && obj->cjson && key && value && value->cjson)
{
cJSON_AddItemToObject(obj->cjson, key, value->cjson);
value->auto_free = false; // 所有权转移
}
}
/**
* @brief 向JSON对象添加数组
*
* @param obj JSON对象
* @param key 属性键
* @param value 数组(所有权转移给父对象)
*/
void json_object_put_array(JsonObject *obj, const char *key, JsonArray *value)
{
if (obj && obj->cjson && key && value && value->cjson)
{
cJSON_AddItemToObject(obj->cjson, key, value->cjson);
value->auto_free = false; // 所有权转移
}
}
/**
* @brief 从JSON对象获取字符串属性
*
* @param obj JSON对象
* @param key 属性键
* @param default_value 默认值(当属性不存在或类型错误时返回)
* @return const char* 字符串值
*/
const char *json_object_get_string(JsonObject *obj, const char *key, const char *default_value)
{
if (!obj || !obj->cjson || !key)
return default_value;
cJSON *item = cJSON_GetObjectItem(obj->cjson, key);
if (cJSON_IsString(item))
{
return item->valuestring;
}
return default_value;
}
/**
* @brief 从JSON对象获取数值属性
*
* @param obj JSON对象
* @param key 属性键
* @param default_value 默认值(当属性不存在或类型错误时返回)
* @return double 数值
*/
double json_object_get_number(JsonObject *obj, const char *key, double default_value)
{
if (!obj || !obj->cjson || !key)
return default_value;
cJSON *item = cJSON_GetObjectItem(obj->cjson, key);
if (cJSON_IsNumber(item))
{
return item->valuedouble;
}
return default_value;
}
/**
* @brief 从JSON对象获取布尔属性
*
* @param obj JSON对象
* @param key 属性键
* @param default_value 默认值(当属性不存在或类型错误时返回)
* @return bool 布尔值
*/
bool json_object_get_bool(JsonObject *obj, const char *key, bool default_value)
{
if (!obj || !obj->cjson || !key)
return default_value;
cJSON *item = cJSON_GetObjectItem(obj->cjson, key);
if (cJSON_IsBool(item))
{
return cJSON_IsTrue(item);
}
return default_value;
}
/**
* @brief 从JSON对象获取子对象
*
* @param obj JSON对象
* @param key 属性键
* @return JsonObject* 子对象(不转移所有权),失败返回NULL
*/
JsonObject *json_object_get_object(JsonObject *obj, const char *key)
{
if (!obj || !obj->cjson || !key)
return NULL;
cJSON *item = cJSON_GetObjectItem(obj->cjson, key);
if (cJSON_IsObject(item))
{
return create_json_object(item, false);
}
return NULL;
}
/**
* @brief 从JSON对象获取数组
*
* @param obj JSON对象
* @param key 属性键
* @return JsonArray* 数组(不转移所有权),失败返回NULL
*/
JsonArray *json_object_get_array(JsonObject *obj, const char *key)
{
if (!obj || !obj->cjson || !key)
return NULL;
cJSON *item = cJSON_GetObjectItem(obj->cjson, key);
if (cJSON_IsArray(item))
{
return create_json_array(item, false);
}
return NULL;
}
// ====================
// JSON 数组操作实现
// ====================
/**
* @brief 创建一个空的JSON数组
*
* @return JsonArray* 新创建的JSON数组
*/
JsonArray *json_array_create()
{
return create_json_array(cJSON_CreateArray(), true);
}
/**
* @brief 从JSON字符串解析创建JSON数组
*
* @param json_str JSON格式的字符串
* @return JsonArray* 解析后的JSON数组,失败返回NULL
*/
JsonArray *json_array_parse(const char *json_str)
{
cJSON *cjson = cJSON_Parse(json_str);
if (!cjson || !cJSON_IsArray(cjson))
{
if (cjson)
cJSON_Delete(cjson);
return NULL;
}
return create_json_array(cjson, true);
}
/**
* @brief 获取JSON数组的大小
*
* @param array JSON数组
* @return int 数组元素个数
*/
int json_array_size(JsonArray *array)
{
if (!array || !array->cjson)
return 0;
return cJSON_GetArraySize(array->cjson);
}
/**
* @brief 向JSON数组添加字符串元素
*
* @param array JSON数组
* @param value 字符串值
*/
void json_array_append_string(JsonArray *array, const char *value)
{
if (array && array->cjson)
{
cJSON_AddItemToArray(array->cjson, cJSON_CreateString(value));
}
}
/**
* @brief 向JSON数组添加数值元素
*
* @param array JSON数组
* @param value 数值
*/
void json_array_append_number(JsonArray *array, double value)
{
if (array && array->cjson)
{
cJSON_AddItemToArray(array->cjson, cJSON_CreateNumber(value));
}
}
/**
* @brief 向JSON数组添加布尔元素
*
* @param array JSON数组
* @param value 布尔值
*/
void json_array_append_bool(JsonArray *array, bool value)
{
if (array && array->cjson)
{
cJSON_AddItemToArray(array->cjson, cJSON_CreateBool(value));
}
}
/**
* @brief 向JSON数组添加null元素
*
* @param array JSON数组
*/
void json_array_append_null(JsonArray *array)
{
if (array && array->cjson)
{
cJSON_AddItemToArray(array->cjson, cJSON_CreateNull());
}
}
/**
* @brief 向JSON数组添加JSON对象
*
* @param array JSON数组
* @param value 要添加的JSON对象(所有权转移给数组)
*/
void json_array_append_object(JsonArray *array, JsonObject *value)
{
if (array && array->cjson && value && value->cjson)
{
cJSON_AddItemToArray(array->cjson, value->cjson);
value->auto_free = false; // 所有权转移
}
}
/**
* @brief 向JSON数组添加子数组
*
* @param array JSON数组
* @param value 要添加的子数组(所有权转移给父数组)
*/
void json_array_append_array(JsonArray *array, JsonArray *value)
{
if (array && array->cjson && value && value->cjson)
{
cJSON_AddItemToArray(array->cjson, value->cjson);
value->auto_free = false; // 所有权转移
}
}
/**
* @brief 从JSON数组获取字符串元素
*
* @param array JSON数组
* @param index 元素索引
* @param default_value 默认值(当索引越界或类型错误时返回)
* @return const char* 字符串值
*/
const char *json_array_get_string(JsonArray *array, int index, const char *default_value)
{
if (!array || !array->cjson || index < 0 || index >= json_array_size(array))
{
return default_value;
}
cJSON *item = cJSON_GetArrayItem(array->cjson, index);
if (cJSON_IsString(item))
{
return item->valuestring;
}
return default_value;
}
/**
* @brief 从JSON数组获取数值元素
*
* @param array JSON数组
* @param index 元素索引
* @param default_value 默认值(当索引越界或类型错误时返回)
* @return double 数值
*/
double json_array_get_number(JsonArray *array, int index, double default_value)
{
if (!array || !array->cjson || index < 0 || index >= json_array_size(array))
{
return default_value;
}
cJSON *item = cJSON_GetArrayItem(array->cjson, index);
if (cJSON_IsNumber(item))
{
return item->valuedouble;
}
return default_value;
}
/**
* @brief 从JSON数组获取布尔元素
*
* @param array JSON数组
* @param index 元素索引
* @param default_value 默认值(当索引越界或类型错误时返回)
* @return bool 布尔值
*/
bool json_array_get_bool(JsonArray *array, int index, bool default_value)
{
if (!array || !array->cjson || index < 0 || index >= json_array_size(array))
{
return default_value;
}
cJSON *item = cJSON_GetArrayItem(array->cjson, index);
if (cJSON_IsBool(item))
{
return cJSON_IsTrue(item);
}
return default_value;
}
/**
* @brief 从JSON数组获取JSON对象元素
*
* @param array JSON数组
* @param index 元素索引
* @return JsonObject* JSON对象(不转移所有权),失败返回NULL
*/
JsonObject *json_array_get_object(JsonArray *array, int index)
{
if (!array || !array->cjson || index < 0 || index >= json_array_size(array))
{
return NULL;
}
cJSON *item = cJSON_GetArrayItem(array->cjson, index);
if (cJSON_IsObject(item))
{
return create_json_object(item, false);
}
return NULL;
}
/**
* @brief 从JSON数组获取子数组元素
*
* @param array JSON数组
* @param index 元素索引
* @return JsonArray* 子数组(不转移所有权),失败返回NULL
*/
JsonArray *json_array_get_array(JsonArray *array, int index)
{
if (!array || !array->cjson || index < 0 || index >= json_array_size(array))
{
return NULL;
}
cJSON *item = cJSON_GetArrayItem(array->cjson, index);
if (cJSON_IsArray(item))
{
return create_json_array(item, false);
}
return NULL;
}
cJSON 库的常用函数接口的表格形式,包含每个函数的简要说明和示例代码。这些函数涵盖了创建、解析、修改和输出 JSON 数据的主要操作。
| 函数接口 | 功能说明 | 示例代码 |
|---|---|---|
| 解析 JSON | ||
cJSON *cJSON_Parse(const char *value) | 解析一个 JSON 字符串并返回一个指向 cJSON 结构体的指针。 | c<br>cJSON *json = cJSON_Parse("{\"name\": \"Alice\"}");<br>if (json == NULL) {<br> // 处理错误<br>}<br> |
void cJSON_Delete(cJSON *c) | 释放由 cJSON_Parse 或其他创建函数分配的内存。 | c<br>cJSON_Delete(json);<br> |
| 创建 JSON | ||
cJSON *cJSON_CreateNull(void) | 创建一个表示 null 的 JSON 节点。 | c<br>cJSON *nullItem = cJSON_CreateNull();<br> |
cJSON *cJSON_CreateBool(cJSON_bool boolean) | 创建一个布尔值的 JSON 节点。 | c<br>cJSON *boolItem = cJSON_CreateBool(1); // true<br> |
cJSON *cJSON_CreateNumber(double num) | 创建一个数字值的 JSON 节点。 | c<br>cJSON *numberItem = cJSON_CreateNumber(123.45);<br> |
cJSON *cJSON_CreateString(const char *string) | 创建一个字符串值的 JSON 节点。 | c<br>cJSON *stringItem = cJSON_CreateString("Hello, World!");<br> |
cJSON *cJSON_CreateArray(void) | 创建一个空的 JSON 数组。 | c<br>cJSON *array = cJSON_CreateArray();<br> |
cJSON *cJSON_CreateObject(void) | 创建一个空的 JSON 对象。 | c<br>cJSON *object = cJSON_CreateObject();<br> |
| 修改 JSON | ||
void cJSON_AddItemToArray(cJSON *array, cJSON *item) | 向 JSON 数组中添加一个项目。 | c<br>cJSON_AddItemToArray(array, cJSON_CreateString("Item1"));<br> |
void cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item) | 向 JSON 对象中添加一个键值对。 | c<br>cJSON_AddItemToObject(object, "key", cJSON_CreateNumber(1));<br> |
void cJSON_ReplaceItemInObject(cJSON *object, const char *string, cJSON *newitem) | 替换 JSON 对象中指定键的值。 | c<br>cJSON_ReplaceItemInObject(object, "key", cJSON_CreateNumber(2));<br> |
| 查询 JSON | ||
cJSON *cJSON_GetObjectItemCaseSensitive(cJSON *object, const char *string) | 获取 JSON 对象中指定键的项,区分大小写。 | c<br>cJSON *item = cJSON_GetObjectItemCaseSensitive(object, "key");<br> |
cJSON_bool cJSON_HasObjectItem(cJSON *object, const char *string) | 检查 JSON 对象中是否存在指定键。 | c<br>if (cJSON_HasObjectItem(object, "key")) {<br> // 处理存在<br>}<br> |
| 输出 JSON | ||
char *cJSON_Print(cJSON *item) | 将 cJSON 结构体转换为格式化的 JSON 字符串。 | c<br>char *json_str = cJSON_Print(json);<br>printf("%s\n", json_str);<br> |
char *cJSON_PrintUnformatted(cJSON *item) | 将 cJSON 结构体转换为无格式的 JSON 字符串(不带空格和换行)。 | c<br>char *json_str = cJSON_PrintUnformatted(json);<br>printf("%s\n", json_str);<br> |
| 其他常用函数 | ||
cJSON_bool cJSON_IsNull(cJSON *item) | 检查一个 cJSON 项是否为 null。 | c<br>if (cJSON_IsNull(item)) {<br> // 处理 null<br>}<br> |
cJSON_bool cJSON_IsBool(cJSON *item) | 检查一个 cJSON 项是否为布尔值。 | c<br>if (cJSON_IsBool(item)) {<br> // 处理布尔值<br>}<br> |
cJSON_bool cJSON_IsNumber(cJSON *item) | 检查一个 cJSON 项是否为数字。 | c<br>if (cJSON_IsNumber(item)) {<br> // 处理数字<br>}<br> |
cJSON_bool cJSON_IsString(cJSON *item) | 检查一个 cJSON 项是否为字符串。 | c<br>if (cJSON_IsString(item)) {<br> // 处理字符串<br>}<br> |
示例代码
一个综合示例,展示了如何使用上述函数来创建、解析、修改和输出 JSON 数据:
#include <stdio.h>
#include <cjson/cJSON.h>
int main()
{
// 创建 JSON 对象
cJSON *root = cJSON_CreateObject();
cJSON_AddItemToObject(root, "name", cJSON_CreateString("Alice"));
cJSON_AddItemToObject(root, "age", cJSON_CreateNumber(30));
cJSON_AddItemToObject(root, "isStudent", cJSON_CreateBool(0));
// 创建 JSON 数组并添加到对象中
cJSON *courses = cJSON_CreateArray();
cJSON_AddItemToArray(courses, cJSON_CreateString("Math"));
cJSON_AddItemToArray(courses, cJSON_CreateString("Science"));
cJSON_AddItemToArray(courses, cJSON_CreateString("History"));
cJSON_AddItemToObject(root, "courses", courses);
// 输出 JSON 字符串
char *json_str = cJSON_Print(root);
printf("Original JSON:\n%s\n", json_str);
// 解析 JSON 字符串
cJSON *parsed = cJSON_Parse(json_str);
if (parsed == NULL)
{
printf("Error parsing JSON\n");
cJSON_Delete(root);
free(json_str);
return 1;
}
// 修改 JSON 数据
cJSON_ReplaceItemInObject(parsed, "age", cJSON_CreateNumber(31));
cJSON_ReplaceItemInObject(parsed, "isStudent", cJSON_CreateBool(1));
// 添加新的键值对
cJSON_AddItemToObject(parsed, "email", cJSON_CreateString("alice@example.com"));
// 输出修改后的 JSON 字符串
char *modified_json_str = cJSON_Print(parsed);
printf("Modified JSON:\n%s\n", modified_json_str);
// 释放内存
cJSON_Delete(root);
cJSON_Delete(parsed);
free(json_str);
free(modified_json_str);
return 0;
}
输出结果
Original JSON:
{
"name": "Alice",
"age": 30,
"isStudent": false,
"courses": [
"Math",
"Science",
"History"
]
}
Modified JSON:
{
"name": "Alice",
"age": 31,
"isStudent": true,
"courses": [
"Math",
"Science",
"History"
],
"email": "alice@example.com"
}
1189

被折叠的 条评论
为什么被折叠?



