C语言如何定义JSON类:从基础到实践的全面指南
在C语言中处理JSON数据时,由于语言本身没有内置的JSON类型支持,我们需要手动定义JSON类(或结构体)来表示JSON的不同数据结构,并实现相应的解析、生成和操作功能,本文将详细介绍如何在C语言中定义JSON类,包括数据结构设计、核心功能实现及实践示例。
JSON数据结构分析
JSON(JavaScript Object Notation)支持六种数据类型:
- 对象(Object):无序键值对集合,如
{"name": "Alice", "age": 30} - 数组(Array):有序值列表,如
[1, "hello", true] - 字符串(String):双引号包裹的字符序列,如
"C Language" - 数字(Number):整数或浮点数,如
123、14 - 布尔值(Boolean):
true或false - 空值(Null):
null
为了在C语言中表示这些类型,我们需要设计一个联合体(union)来存储不同类型的值,并通过枚举(enum)标记当前数据的具体类型。
JSON类的核心结构定义
基础数据结构
首先定义JSON值的类型枚举和联合体,用于存储不同类型的JSON数据:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
// JSON值类型枚举
typedef enum {
JSON_NULL,
JSON_BOOLEAN,
JSON_NUMBER,
JSON_STRING,
JSON_ARRAY,
JSON_OBJECT
} JsonType;
// JSON值联合体(存储具体数据)
typedef union {
bool boolean; // 布尔值
double number; // 数字
char* string; // 字符串(需动态分配内存)
struct JsonArray* array; // 数组
struct JsonObject* object; // 对象
} JsonValueData;
// JSON数组结构(有序值列表)
typedef struct JsonArray {
JsonValue** values; // 存储JSON值的指针数组
size_t size; // 当前元素数量
size_t capacity; // 当前容量(动态扩容)
} JsonArray;
// JSON对象结构(键值对)
typedef struct JsonObject {
char** keys; // 键的数组(字符串)
JsonValue** values; // 对应值的数组
size_t size; // 键值对数量
size_t capacity; // 当前容量
} JsonObject;
// JSON值结构(最终对外暴露的“类”)
typedef struct {
JsonType type; // 值类型
JsonValueData data; // 值数据(通过联合体存储)
} JsonValue;
辅助结构说明
JsonType枚举:明确标识JSON值的具体类型,避免数据混淆。JsonValueData联合体:通过共享内存空间存储不同类型的数据,节省内存(boolean和number不会同时存在)。JsonArray结构:动态数组实现,支持扩容(类似C++的std::vector),存储JsonValue指针的列表。JsonObject结构:键值对集合,keys和values数组按索引对应,支持动态扩容。
JSON类的核心功能实现
内存管理:初始化与释放
JSON数据结构涉及动态内存分配(如字符串、数组、对象),需提供初始化和释放函数,避免内存泄漏。
(1)初始化JSON值
// 创建一个JSON NULL值
JsonValue* json_create_null() {
JsonValue* value = (JsonValue*)malloc(sizeof(JsonValue));
if (!value) return NULL;
value->type = JSON_NULL;
return value;
}
// 创建JSON布尔值
JsonValue* json_create_bool(bool b) {
JsonValue* value = (JsonValue*)malloc(sizeof(JsonValue));
if (!value) return NULL;
value->type = JSON_BOOLEAN;
value->data.boolean = b;
return value;
}
// 创建JSON数字
JsonValue* json_create_number(double num) {
JsonValue* value = (JsonValue*)malloc(sizeof(JsonValue));
if (!value) return NULL;
value->type = JSON_NUMBER;
value->data.number = num;
return value;
}
// 创建JSON字符串(需复制输入字符串)
JsonValue* json_create_string(const char* str) {
JsonValue* value = (JsonValue*)malloc(sizeof(JsonValue));
if (!value) return NULL;
value->type = JSON_STRING;
value->data.string = strdup(str); // 复制字符串(需后续free)
if (!value->data.string) {
free(value);
return NULL;
}
return value;
}
// 创建JSON空数组
JsonValue* json_create_array() {
JsonValue* value = (JsonValue*)malloc(sizeof(JsonValue));
if (!value) return NULL;
value->type = JSON_ARRAY;
JsonArray* array = (JsonArray*)malloc(sizeof(JsonArray));
if (!array) {
free(value);
return NULL;
}
array->values = NULL;
array->size = 0;
array->capacity = 0;
value->data.array = array;
return value;
}
// 创建JSON空对象
JsonValue* json_create_object() {
JsonValue* value = (JsonValue*)malloc(sizeof(JsonValue));
if (!value) return NULL;
value->type = JSON_OBJECT;
JsonObject* obj = (JsonObject*)malloc(sizeof(JsonObject));
if (!obj) {
free(value);
return NULL;
}
obj->keys = NULL;
obj->values = NULL;
obj->size = 0;
obj->capacity = 0;
value->data.object = obj;
return value;
}
(2)释放JSON值(递归释放嵌套结构)
// 释放JSON数组
static void json_free_array(JsonArray* array) {
if (!array) return;
for (size_t i = 0; i < array->size; i++) {
json_free_value(array->values[i]); // 递归释放数组元素
}
free(array->values);
free(array);
}
// 释放JSON对象
static void json_free_object(JsonObject* obj) {
if (!obj) return;
for (size_t i = 0; i < obj->size; i++) {
free(obj->keys[i]); // 释放键字符串
json_free_value(obj->values[i]); // 递归释放值
}
free(obj->keys);
free(obj->values);
free(obj);
}
// 释放JSON值(对外接口)
void json_free_value(JsonValue* value) {
if (!value) return;
switch (value->type) {
case JSON_STRING:
free(value->data.string);
break;
case JSON_ARRAY:
json_free_array(value->data.array);
break;
case JSON_OBJECT:
json_free_object(value->data.object);
break;
default: // NULL/BOOLEAN/NUMBER无需释放动态内存
break;
}
free(value);
}
数组操作:添加元素
// 向JSON数组添加元素(动态扩容)
bool json_array_add(JsonValue* array_value, JsonValue* element) {
if (array_value->type != JSON_ARRAY) return false;
JsonArray* array = array_value->data.array;
// 检查容量,不够则扩容(初始容量为4,每次翻倍)
if (array->size >= array->capacity) {
size_t new_capacity = array->capacity == 0 ? 4 : array->capacity * 2;
JsonValue** new_values = (JsonValue**)realloc(array->values, new_capacity * sizeof(JsonValue*));
if (!new_values) return false;
array->values = new_values;
array->capacity = new_capacity;
}
array->values[array->size++] = element;
return true;
}
对象操作:添加键值对
// 向JSON对象添加键值对(键需唯一)
bool json_object_add(JsonValue* obj_value, const char* key, JsonValue* value) {
if (obj_value->type != JSON_OBJECT) return false;
JsonObject* obj = obj_value->data.object;
// 检查键是否已存在(简单线性查找,实际场景可用哈希表优化)
for (size_t i = 0; i < obj->size; i++) {
if (strcmp(obj->keys[i], key) == 0) {
json_free_value(obj->values[i]); // 释放旧值
obj->values[i] = value;
return true;
}
}
// 检查容量,不够则扩容
if (obj->size >= obj->capacity) {
size_t new_capacity = obj->capacity == 0 ? 4


还没有评论,来说两句吧...