# cJSON **Repository Path**: Naezaer/cJSON ## Basic Information - **Project Name**: cJSON - **Description**: C语言交互JSON数据 - **Primary Language**: Unknown - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 1 - **Forks**: 0 - **Created**: 2025-08-19 - **Last Updated**: 2025-08-25 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 【C/C++】C语言实现JSON解析器1 JSON(JavaScript Object Notation)作为一种轻量级的、基于文本的、可读的数据交换通用格式,它几乎无处不在。但你是否好奇过高级编程语言是如何解析和操作JSON格式的数据吗?或者换个角度来讲,你是否好奇过高级编程语言自身是如何被编译器翻译的吗?或许通过这篇文章你能找到答案。 ## 一、JSON解析器核心功能设计 这期主要侧重于词法/语法/语义分析,目标是实现一个完整且标准的JSON语法的解析器,从而实现JSON数据到C语言数据的转换(反序列化)。核心功能包括: - 解析数字(整数/小数/指数)、布尔值(true/false)和null; - 解析JSON对象(`{}`)、数组(`[]`)、字符串(`""`) - 处理转义字符(如`\"`、`\\`、`\n`、UNICODE字符等待) - 提供友好的语法错误提示 - 提供安全高效的内存管理(下期继续完善并增加增删改查等功能) ## 二、数据结构设计 JSON有6种基础类型,用C语言的结构体和枚举来映射: ```c // JSON数据类型枚举 typedef enum { JSON_NULL, // null JSON_BOOL, // true/false JSON_NUMBER, // 数字(double) JSON_STRING, // 字符串(char*) JSON_ARRAY, // 数组(链表结构) JSON_OBJECT // 对象(键值对链表) } JSONType; // 数组结构(链表节点) struct JSONArray { JSONNode* elements; // 数组元素 JSONArray* next; // 下一个元素 }; // 对象键值对结构(链表节点) struct JSONOject { char* key; // 键 JSONNode* value; // 值 JSONOject* next; // 下一个键值对 }; // JSON节点(核心结构体) struct JSONNode { JSONType type; // 节点类型 union { // 联合体存储不同类型的值 bool boolean; // JSON_BOOL double number; // JSON_NUMBER char* string; // JSON_STRING JSONArray* array;// JSON_ARRAY JSONOject* object;// JSON_OBJECT } data; }; ``` **设计亮点**: - 使用**联合体(union)** 节省内存,同一节点只存储一种类型的值 - 数组和对象采用**链表存储**,灵活处理动态长度 - 节点类型用枚举标记,便于后续递归处理 ## 三、核心解析逻辑 解析字符串常用的方法有递归下降解析和状态机解析等,而JSON是嵌套结构,最适合用**递归下降解析法**处理。核心思路是: 1. 从根节点开始解析 2. 根据当前字符判断值类型(对象/数组/字符串等) 3. 调用对应解析函数,返回子节点 4. 递归处理嵌套结构 ```text # 用正则表达式(编译原理知识点)表示大致语法是这样的: JSON: Value Value: Null | Boolean | Number | String | Object | Array Null: null Boolean: true | false Number: [+-]?[0-9]+(\.[0-9]+)?([eE][+-]?[0-9]+)? String: "([^"\\]|\\.)*" Object: "{" (String ":" Value ("," String ":" Value)*)? "}" Array: "[" (Value ("," Value)*)? "]" ``` ### 3.1 顶层调度函数 ```c // 解析JSON值(核心调度) static JSONNode* json_parse_value(const char** json) { skip_whitespace(json); if (!**json) return NULL; switch (**json) { case 'n': return json_parse_null(json); case 't': case 'f': return json_parse_boolean(json); case '-': case '0'...'9': return json_parse_number(json); case '"': return json_parse_string(json); case '{': return json_parse_object(json); case '[': return json_parse_array(json); default: json_syntax_error("unexpected token"); return NULL; } } ``` ### 3.2 字符串解析 字符串解析需要处理转义字符和边界检查: ```c static JSONNode* json_parse_string(const char** json) { json_move_position(json, 1); // 跳过开头的" char* buffer = malloc(STRING_BUFFER_MAX_LENGTH); char* buf_ptr = buffer; while (**json && **json != '"') { if (**json == '\\') { // 处理转义字符 *buf_ptr++ = parse_escape_char(json); } else { *buf_ptr++ = **json; json_move_position(json, 1); } } if (**json != '"') { // 检查闭合 json_syntax_error("unclosed string"); free(buffer); return NULL; } json_move_position(json, 1); // 跳过结尾的" *buf_ptr = '\0'; return json_create_node(JSON_STRING, buffer); } // 转义字符映射 static char parse_escape_char(const char** json) { (*json)++; switch (**json) { case '"': return '"'; case '\\': return '\\'; case 'n': return '\n'; case 't': return '\t'; // 其他转义字符... } } ``` ### 3.3 数组解析 ```c static JSONNode* json_parse_array(const char** json) { json_move_position(json, 1); // 跳过[ JSONArray* head = NULL; JSONArray** current = &head; while (**json && **json != ']') { // 解析数组元素(递归) JSONNode* elem = json_parse_value(json); if (!elem) return NULL; // 插入链表 *current = malloc(sizeof(JSONArray)); (*current)->elements = elem; (*current)->next = NULL; current = &(*current)->next; // 处理逗号分隔 if (**json == ',') { json_move_position(json, 1); } else if (**json != ']') { json_syntax_error("missing comma in array"); return NULL; } } json_move_position(json, 1); // 跳过] return json_create_node(JSON_ARRAY, head); } ``` ## 四、内存管理 C语言需要手动管理内存: ```c // 释放JSON节点 void json_free(JSONNode* node) { if (!node) return; switch (node->type) { case JSON_STRING: free(node->data.string); // 释放字符串 break; case JSON_ARRAY: free_array(node->data.array); // 释放数组链表 break; case JSON_OBJECT: free_object(node->data.object); // 释放对象链表 break; } free(node); // 释放节点本身 } // 释放数组链表 static void free_array(JSONArray* arr) { while (arr) { JSONArray* next = arr->next; json_free(arr->elements); // 递归释放元素 free(arr); arr = next; } } ``` ## 五、错误处理 解析器需要提供友好的错误提示(跟踪行列号): ```c static uint64_t g_row = 1; // 当前行号 static uint64_t g_col = 1; // 当前列号 // 移动解析位置时更新行列号 static void json_move_position(const char** json, uint64_t length) { for (uint64_t i = 0; i < length; i++) { if (**json == '\n') { g_row++; g_col = 1; } else { g_col++; } (*json)++; } } // 语法错误提示 static void json_syntax_error(const char* message) { fprintf(stderr, "ERROR: %s at line %lu, column %lu\n", message, g_row, g_col); } ``` 剩余功能(增删改查JSON数据、UNICODE支持、序列化等等)下期继续完善。 ## 完整源码地址 - [https://gitee.com/Naezaer/cJSON.git](https://gitee.com/Naezaer/cJSON.git)