├── .gitignore ├── Makefile ├── README.md ├── examples └── main.c ├── include ├── json_builder.h └── json_parser.h ├── logo.svg ├── src ├── json_builder.c └── json_parser.c └── test ├── test_json.c ├── unity.c └── unity.h /.gitignore: -------------------------------------------------------------------------------- 1 | # Build directory 2 | build/ 3 | 4 | # Object files 5 | *.o 6 | *.ko 7 | *.obj 8 | *.elf 9 | 10 | # Precompiled Headers 11 | *.gch 12 | *.pch 13 | 14 | # Libraries 15 | *.lib 16 | *.a 17 | *.la 18 | *.lo 19 | 20 | # Shared objects (inc. Windows DLLs) 21 | *.dll 22 | *.so 23 | *.so.* 24 | *.dylib 25 | 26 | # Executables 27 | *.exe 28 | *.out 29 | *.app 30 | *.i*86 31 | *.x86_64 32 | *.hex 33 | 34 | # Debug files 35 | *.dSYM/ 36 | *.su 37 | *.idb 38 | *.pdb 39 | 40 | # Editor files 41 | .vscode/ 42 | .idea/ 43 | *.swp 44 | *~ 45 | 46 | # OS specific files 47 | .DS_Store 48 | Thumbs.db 49 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | CC = gcc 2 | CFLAGS = -Wall -Wextra -Iinclude -Itest 3 | LDFLAGS = 4 | 5 | # 目标文件 6 | LIB_NAME = libjson 7 | MAIN_TARGET = json_example 8 | TEST_TARGET = json_test 9 | 10 | # 目录结构 11 | SRC_DIR = src 12 | INCLUDE_DIR = include 13 | TEST_DIR = test 14 | EXAMPLES_DIR = examples 15 | BUILD_DIR = build 16 | 17 | # 源文件 18 | LIB_SOURCES = $(wildcard $(SRC_DIR)/*.c) 19 | EXAMPLE_SOURCES = $(wildcard $(EXAMPLES_DIR)/*.c) 20 | TEST_SOURCES = $(wildcard $(TEST_DIR)/*.c) 21 | 22 | # 目标文件 23 | LIB_OBJECTS = $(patsubst $(SRC_DIR)/%.c,$(BUILD_DIR)/%.o,$(LIB_SOURCES)) 24 | EXAMPLE_OBJECTS = $(patsubst $(EXAMPLES_DIR)/%.c,$(BUILD_DIR)/%.o,$(EXAMPLE_SOURCES)) 25 | TEST_OBJECTS = $(patsubst $(TEST_DIR)/%.c,$(BUILD_DIR)/%.o,$(TEST_SOURCES)) 26 | 27 | # 创建build目录 28 | $(BUILD_DIR): 29 | mkdir -p $(BUILD_DIR) 30 | 31 | # 默认目标 32 | all: $(BUILD_DIR) $(LIB_NAME) $(MAIN_TARGET) $(TEST_TARGET) 33 | 34 | # 静态库 35 | $(LIB_NAME): $(LIB_OBJECTS) 36 | ar rcs $(BUILD_DIR)/$@.a $^ 37 | 38 | # 示例程序 39 | $(MAIN_TARGET): $(EXAMPLE_OBJECTS) $(LIB_NAME) 40 | $(CC) $(CFLAGS) -o $(BUILD_DIR)/$@ $(EXAMPLE_OBJECTS) -L$(BUILD_DIR) -ljson $(LDFLAGS) 41 | 42 | # 测试程序 43 | $(TEST_TARGET): $(TEST_OBJECTS) $(LIB_NAME) 44 | $(CC) $(CFLAGS) -o $(BUILD_DIR)/$@ $(TEST_OBJECTS) -L$(BUILD_DIR) -ljson $(LDFLAGS) 45 | 46 | # 编译规则 - 库源文件 47 | $(BUILD_DIR)/%.o: $(SRC_DIR)/%.c | $(BUILD_DIR) 48 | $(CC) $(CFLAGS) -c $< -o $@ 49 | 50 | # 编译规则 - 示例源文件 51 | $(BUILD_DIR)/%.o: $(EXAMPLES_DIR)/%.c | $(BUILD_DIR) 52 | $(CC) $(CFLAGS) -c $< -o $@ 53 | 54 | # 编译规则 - 测试源文件 55 | $(BUILD_DIR)/%.o: $(TEST_DIR)/%.c | $(BUILD_DIR) 56 | $(CC) $(CFLAGS) -c $< -o $@ 57 | 58 | # 运行测试 59 | test: $(TEST_TARGET) 60 | $(BUILD_DIR)/$(TEST_TARGET) 61 | 62 | # 运行示例 63 | run: $(MAIN_TARGET) 64 | $(BUILD_DIR)/$(MAIN_TARGET) 65 | 66 | # 清理 67 | clean: 68 | rm -rf $(BUILD_DIR) 69 | 70 | # 安装 71 | install: $(LIB_NAME) 72 | mkdir -p /usr/local/include/json 73 | mkdir -p /usr/local/lib 74 | cp $(INCLUDE_DIR)/*.h /usr/local/include/json/ 75 | cp $(BUILD_DIR)/$(LIB_NAME).a /usr/local/lib/ 76 | 77 | # 卸载 78 | uninstall: 79 | rm -rf /usr/local/include/json 80 | rm -f /usr/local/lib/$(LIB_NAME).a 81 | 82 | .PHONY: all test run clean install uninstall 83 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 | lightjson logo 3 |
4 | 5 | # lightjson - JSON Builder and Parser 6 | 7 | A lightweight JSON builder and parser library implemented in C. 8 | 9 | ## Project Structure 10 | 11 | ``` 12 | . 13 | ├── include/ # Public header files 14 | │ ├── json_builder.h # JSON builder header file 15 | │ └── json_parser.h # JSON parser header file 16 | ├── src/ # Source code 17 | │ ├── json_builder.c # JSON builder implementation 18 | │ └── json_parser.c # JSON parser implementation 19 | ├── test/ # Test code 20 | │ ├── test_json.c # Test cases 21 | │ ├── unity.c # Unity test framework 22 | │ └── unity.h # Unity test framework header 23 | ├── examples/ # Example code 24 | │ └── main.c # Usage example 25 | ├── docs/ # Documentation 26 | ├── build/ # Build directory 27 | └── Makefile # Build script 28 | ``` 29 | 30 | ## Features 31 | 32 | - JSON Builder: Create and manipulate JSON objects and arrays 33 | - JSON Parser: Parse JSON strings into in-memory data structures 34 | - UTF-8 encoding support 35 | - Support for nested objects and arrays 36 | - Support for special characters and escaping 37 | 38 | ## Build and Usage 39 | 40 | ### Building the Library 41 | 42 | ```bash 43 | make 44 | ``` 45 | 46 | ### Running Tests 47 | 48 | ```bash 49 | make test 50 | ``` 51 | 52 | ### Example 53 | 54 | Check `examples/main.c` to learn how to use the library. 55 | 56 | ## API Documentation 57 | 58 | ### JSON Builder 59 | 60 | - `json_builder_create()` - Create a JSON builder 61 | - `json_builder_free()` - Free a JSON builder 62 | - `json_builder_start_object()` - Start a JSON object 63 | - `json_builder_end_object()` - End a JSON object 64 | - `json_builder_start_array()` - Start a JSON array 65 | - `json_builder_end_array()` - End a JSON array 66 | - `json_builder_add_string()` - Add a string key-value pair 67 | - `json_builder_add_number()` - Add a number key-value pair 68 | - `json_builder_add_bool()` - Add a boolean key-value pair 69 | - `json_builder_add_null()` - Add a null key-value pair 70 | - `json_builder_append()` - Add a raw string 71 | - `json_builder_get_string()` - Get the built JSON string 72 | 73 | ### JSON Parser 74 | 75 | - `json_parse()` - Parse a JSON string 76 | - `json_value_free()` - Free a JSON value 77 | - `json_value_get_string()` - Get a string value 78 | - `json_value_get_number()` - Get a number value 79 | - `json_value_get_bool()` - Get a boolean value 80 | - `json_value_get_object()` - Get an object value 81 | - `json_value_get_array()` - Get an array value 82 | - `json_get_error()` - Get error information 83 | 84 | ## License 85 | 86 | [MIT License](LICENSE) 87 | -------------------------------------------------------------------------------- /examples/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "json_builder.h" 3 | #include "json_parser.h" 4 | 5 | int main() { 6 | // 设置控制台为UTF-8编码 7 | set_console_utf8(); 8 | 9 | // 创建一个JSON字符串用于测试 10 | JsonBuilder* builder = json_builder_create(1024); 11 | json_builder_start_object(builder); 12 | json_builder_add_string(builder, "name", "张三"); 13 | json_builder_add_number(builder, "age", 25); 14 | json_builder_add_bool(builder, "is_student", true); 15 | json_builder_add_null(builder, "address"); 16 | 17 | // 添加一个数组 18 | json_builder_append(builder, "\"hobbies\":"); 19 | json_builder_start_array(builder); 20 | json_builder_append(builder, "\"读书\","); 21 | json_builder_append(builder, "\"音乐\","); 22 | json_builder_append(builder, "\"编程\""); 23 | json_builder_end_array(builder); 24 | json_builder_append(builder, ","); 25 | 26 | // 添加一个嵌套对象 27 | json_builder_append(builder, "\"contact\":"); 28 | json_builder_start_object(builder); 29 | json_builder_add_string(builder, "email", "zhangsan@example.com"); 30 | json_builder_add_string(builder, "phone", "123456789"); 31 | json_builder_end_object(builder); 32 | 33 | json_builder_end_object(builder); 34 | 35 | // 获取构建的JSON字符串 36 | const char* json_str = json_builder_get_string(builder); 37 | printf("构建的JSON字符串:\n%s\n\n", json_str); 38 | 39 | // 解析JSON字符串 40 | JsonValue* value = json_parse(json_str); 41 | if (!value) { 42 | printf("解析错误: %s\n", json_get_error()); 43 | json_builder_free(builder); 44 | return 1; 45 | } 46 | 47 | // 访问解析后的值 48 | JsonObject* obj = json_value_get_object(value); 49 | if (obj) { 50 | for (size_t i = 0; i < obj->size; i++) { 51 | printf("键: %s, ", obj->pairs[i].key); 52 | JsonValue* v = obj->pairs[i].value; 53 | switch (v->type) { 54 | case JSON_STRING: 55 | printf("值(字符串): %s\n", v->value.string); 56 | break; 57 | case JSON_NUMBER: 58 | printf("值(数字): %f\n", v->value.number); 59 | break; 60 | case JSON_BOOL: 61 | printf("值(布尔): %s\n", v->value.boolean ? "true" : "false"); 62 | break; 63 | case JSON_NULL: 64 | printf("值: null\n"); 65 | break; 66 | case JSON_ARRAY: { 67 | printf("值(数组): ["); 68 | JsonArray* arr = v->value.array; 69 | for (size_t j = 0; j < arr->size; j++) { 70 | JsonValue* elem = arr->elements[j]; 71 | if (elem->type == JSON_STRING) { 72 | printf("\"%s\"", elem->value.string); 73 | } 74 | if (j < arr->size - 1) printf(", "); 75 | } 76 | printf("]\n"); 77 | break; 78 | } 79 | case JSON_OBJECT: { 80 | printf("值(对象): {\n"); 81 | JsonObject* nested = v->value.object; 82 | for (size_t j = 0; j < nested->size; j++) { 83 | printf(" %s: ", nested->pairs[j].key); 84 | JsonValue* nested_v = nested->pairs[j].value; 85 | if (nested_v->type == JSON_STRING) { 86 | printf("\"%s\"\n", nested_v->value.string); 87 | } 88 | } 89 | printf("}\n"); 90 | break; 91 | } 92 | } 93 | } 94 | } 95 | 96 | // 测试错误处理 97 | printf("\n测试错误处理:\n"); 98 | const char* invalid_json = "{\"key\":}"; 99 | JsonValue* invalid_value = json_parse(invalid_json); 100 | if (!invalid_value) { 101 | printf("预期的错误: %s\n", json_get_error()); 102 | } 103 | 104 | // 释放资源 105 | json_value_free(value); 106 | json_builder_free(builder); 107 | 108 | return 0; 109 | } -------------------------------------------------------------------------------- /include/json_builder.h: -------------------------------------------------------------------------------- 1 | #ifndef JSON_BUILDER_H 2 | #define JSON_BUILDER_H 3 | 4 | #include 5 | #include 6 | 7 | typedef struct { 8 | char* buffer; 9 | size_t capacity; 10 | size_t length; 11 | } JsonBuilder; 12 | 13 | // 创建和销毁 14 | JsonBuilder* json_builder_create(size_t initial_capacity); 15 | void json_builder_free(JsonBuilder* builder); 16 | 17 | // 基本操作 18 | bool json_builder_ensure_capacity(JsonBuilder* builder, size_t additional); 19 | bool json_builder_append(JsonBuilder* builder, const char* str); 20 | const char* json_builder_get_string(JsonBuilder* builder); 21 | 22 | // JSON结构操作 23 | bool json_builder_start_object(JsonBuilder* builder); 24 | bool json_builder_end_object(JsonBuilder* builder); 25 | bool json_builder_start_array(JsonBuilder* builder); 26 | bool json_builder_end_array(JsonBuilder* builder); 27 | 28 | // 添加各种类型的键值对 29 | bool json_builder_add_string(JsonBuilder* builder, const char* key, const char* value); 30 | bool json_builder_add_number(JsonBuilder* builder, const char* key, double value); 31 | bool json_builder_add_bool(JsonBuilder* builder, const char* key, bool value); 32 | bool json_builder_add_null(JsonBuilder* builder, const char* key); 33 | 34 | // 控制台编码设置 35 | void set_console_utf8(); 36 | 37 | #endif // JSON_BUILDER_H -------------------------------------------------------------------------------- /include/json_parser.h: -------------------------------------------------------------------------------- 1 | #ifndef JSON_PARSER_H 2 | #define JSON_PARSER_H 3 | 4 | #include 5 | #include 6 | 7 | // JSON值类型枚举 8 | typedef enum { 9 | JSON_NULL, 10 | JSON_BOOL, 11 | JSON_NUMBER, 12 | JSON_STRING, 13 | JSON_ARRAY, 14 | JSON_OBJECT 15 | } JsonValueType; 16 | 17 | // 前向声明 18 | struct JsonValue; 19 | struct JsonObject; 20 | struct JsonArray; 21 | 22 | // JSON值结构体 23 | typedef struct JsonValue { 24 | JsonValueType type; 25 | union { 26 | bool boolean; 27 | double number; 28 | char* string; 29 | struct JsonArray* array; 30 | struct JsonObject* object; 31 | } value; 32 | } JsonValue; 33 | 34 | // JSON对象键值对 35 | typedef struct JsonKeyValue { 36 | char* key; 37 | JsonValue* value; 38 | } JsonKeyValue; 39 | 40 | // JSON对象结构体 41 | typedef struct JsonObject { 42 | JsonKeyValue* pairs; 43 | size_t size; 44 | size_t capacity; 45 | } JsonObject; 46 | 47 | // JSON数组结构体 48 | typedef struct JsonArray { 49 | JsonValue** elements; 50 | size_t size; 51 | size_t capacity; 52 | } JsonArray; 53 | 54 | // 解析器结构体 55 | typedef struct { 56 | const char* json; 57 | size_t pos; 58 | size_t len; 59 | } JsonParser; 60 | 61 | // 创建和销毁函数 62 | JsonParser* json_parser_create(const char* json); 63 | void json_parser_free(JsonParser* parser); 64 | 65 | // 解析函数 66 | JsonValue* json_parse(const char* json); 67 | JsonValue* json_parse_value(JsonParser* parser); 68 | JsonObject* json_parse_object(JsonParser* parser); 69 | JsonArray* json_parse_array(JsonParser* parser); 70 | char* json_parse_string(JsonParser* parser); 71 | double json_parse_number(JsonParser* parser); 72 | bool json_parse_bool(JsonParser* parser); 73 | void json_parse_null(JsonParser* parser); 74 | 75 | // 值操作函数 76 | void json_value_free(JsonValue* value); 77 | const char* json_value_get_string(JsonValue* value); 78 | double json_value_get_number(JsonValue* value); 79 | bool json_value_get_bool(JsonValue* value); 80 | JsonObject* json_value_get_object(JsonValue* value); 81 | JsonArray* json_value_get_array(JsonValue* value); 82 | 83 | // 错误处理 84 | const char* json_get_error(void); 85 | 86 | #endif // JSON_PARSER_H -------------------------------------------------------------------------------- /logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 11 | 12 | 13 | 15 | 16 | 17 | 18 | 19 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | light 28 | 29 | 30 | 31 | json 32 | 33 | 34 | 35 | 36 | 37 | Lightweight JSON Parser & Builder for C 38 | 39 | 40 | -------------------------------------------------------------------------------- /src/json_builder.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | typedef struct { 7 | char* buffer; 8 | size_t capacity; 9 | size_t length; 10 | } JsonBuilder; 11 | 12 | // 初始化JSON构建器 13 | JsonBuilder* json_builder_create(size_t initial_capacity) { 14 | JsonBuilder* builder = (JsonBuilder*)malloc(sizeof(JsonBuilder)); 15 | if (!builder) return NULL; 16 | 17 | builder->buffer = (char*)malloc(initial_capacity); 18 | if (!builder->buffer) { 19 | free(builder); 20 | return NULL; 21 | } 22 | 23 | builder->capacity = initial_capacity; 24 | builder->length = 0; 25 | builder->buffer[0] = '\0'; 26 | 27 | return builder; 28 | } 29 | 30 | // 确保缓冲区有足够空间 31 | bool json_builder_ensure_capacity(JsonBuilder* builder, size_t additional) { 32 | if (builder->length + additional + 1 > builder->capacity) { 33 | size_t new_capacity = builder->capacity * 2; 34 | if (new_capacity < builder->length + additional + 1) 35 | new_capacity = builder->length + additional + 1; 36 | 37 | char* new_buffer = (char*)realloc(builder->buffer, new_capacity); 38 | if (!new_buffer) return false; 39 | 40 | builder->buffer = new_buffer; 41 | builder->capacity = new_capacity; 42 | } 43 | return true; 44 | } 45 | 46 | // 添加字符串到构建器 47 | bool json_builder_append(JsonBuilder* builder, const char* str) { 48 | size_t len = strlen(str); 49 | if (!json_builder_ensure_capacity(builder, len)) return false; 50 | 51 | strcpy(builder->buffer + builder->length, str); 52 | builder->length += len; 53 | 54 | return true; 55 | } 56 | 57 | // 开始一个新的JSON对象 58 | bool json_builder_start_object(JsonBuilder* builder) { 59 | return json_builder_append(builder, "{"); 60 | } 61 | 62 | // 结束当前JSON对象 63 | bool json_builder_end_object(JsonBuilder* builder) { 64 | // 移除最后一个逗号(如果有) 65 | if (builder->length > 0 && builder->buffer[builder->length - 1] == ',') { 66 | builder->buffer[builder->length - 1] = '}'; 67 | } else { 68 | if (!json_builder_append(builder, "}")) return false; 69 | } 70 | return true; 71 | } 72 | 73 | // 开始一个新的JSON数组 74 | bool json_builder_start_array(JsonBuilder* builder) { 75 | return json_builder_append(builder, "["); 76 | } 77 | 78 | // 结束当前JSON数组 79 | bool json_builder_end_array(JsonBuilder* builder) { 80 | // 移除最后一个逗号(如果有) 81 | if (builder->length > 0 && builder->buffer[builder->length - 1] == ',') { 82 | builder->buffer[builder->length - 1] = ']'; 83 | } else { 84 | if (!json_builder_append(builder, "]")) return false; 85 | } 86 | return true; 87 | } 88 | 89 | // 添加字符串键值对 90 | bool json_builder_add_string(JsonBuilder* builder, const char* key, const char* value) { 91 | if (!json_builder_ensure_capacity(builder, strlen(key) + strlen(value) + 10)) 92 | return false; 93 | 94 | char* escaped_value = NULL; 95 | size_t escaped_len = 0; 96 | 97 | // 简单的字符串转义处理 98 | for (const char* p = value; *p; p++) { 99 | if (*p == '\"' || *p == '\\' || *p == '\n' || *p == '\r' || *p == '\t') 100 | escaped_len += 2; 101 | else 102 | escaped_len++; 103 | } 104 | 105 | escaped_value = (char*)malloc(escaped_len + 1); 106 | if (!escaped_value) return false; 107 | 108 | char* q = escaped_value; 109 | for (const char* p = value; *p; p++) { 110 | if (*p == '\"') { *q++ = '\\'; *q++ = '\"'; } 111 | else if (*p == '\\') { *q++ = '\\'; *q++ = '\\'; } 112 | else if (*p == '\n') { *q++ = '\\'; *q++ = 'n'; } 113 | else if (*p == '\r') { *q++ = '\\'; *q++ = 'r'; } 114 | else if (*p == '\t') { *q++ = '\\'; *q++ = 't'; } 115 | else *q++ = *p; 116 | } 117 | *q = '\0'; 118 | 119 | char temp[1024]; 120 | sprintf(temp, "\"%s\":\"%s\",", key, escaped_value); 121 | free(escaped_value); 122 | 123 | return json_builder_append(builder, temp); 124 | } 125 | 126 | // 添加数字键值对 127 | bool json_builder_add_number(JsonBuilder* builder, const char* key, double value) { 128 | if (!json_builder_ensure_capacity(builder, strlen(key) + 32)) 129 | return false; 130 | 131 | char temp[1024]; 132 | sprintf(temp, "\"%s\":%.10g,", key, value); 133 | 134 | return json_builder_append(builder, temp); 135 | } 136 | 137 | // 添加布尔键值对 138 | bool json_builder_add_bool(JsonBuilder* builder, const char* key, bool value) { 139 | if (!json_builder_ensure_capacity(builder, strlen(key) + 10)) 140 | return false; 141 | 142 | char temp[1024]; 143 | sprintf(temp, "\"%s\":%s,", key, value ? "true" : "false"); 144 | 145 | return json_builder_append(builder, temp); 146 | } 147 | 148 | // 添加null键值对 149 | bool json_builder_add_null(JsonBuilder* builder, const char* key) { 150 | if (!json_builder_ensure_capacity(builder, strlen(key) + 10)) 151 | return false; 152 | 153 | char temp[1024]; 154 | sprintf(temp, "\"%s\":null,", key); 155 | 156 | return json_builder_append(builder, temp); 157 | } 158 | 159 | // 获取构建的JSON字符串 160 | const char* json_builder_get_string(JsonBuilder* builder) { 161 | return builder->buffer; 162 | } 163 | 164 | // 释放JSON构建器 165 | void json_builder_free(JsonBuilder* builder) { 166 | if (builder) { 167 | free(builder->buffer); 168 | free(builder); 169 | } 170 | } 171 | 172 | // 新增函数:设置控制台编码 173 | void set_console_utf8() { 174 | #ifdef _WIN32 175 | // 设置控制台输出代码页为UTF-8 176 | system("chcp 65001 > nul"); 177 | #endif 178 | } -------------------------------------------------------------------------------- /src/json_parser.c: -------------------------------------------------------------------------------- 1 | #include "json_parser.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | // 错误消息缓冲区 8 | static char error_message[256] = {0}; 9 | 10 | // 设置错误消息 11 | static void set_error(const char* msg) { 12 | strncpy(error_message, msg, sizeof(error_message) - 1); 13 | } 14 | 15 | // 获取错误消息 16 | const char* json_get_error(void) { 17 | return error_message; 18 | } 19 | 20 | // 创建解析器 21 | JsonParser* json_parser_create(const char* json) { 22 | JsonParser* parser = (JsonParser*)malloc(sizeof(JsonParser)); 23 | if (!parser) { 24 | set_error("内存分配失败"); 25 | return NULL; 26 | } 27 | parser->json = json; 28 | parser->pos = 0; 29 | parser->len = strlen(json); 30 | return parser; 31 | } 32 | 33 | // 跳过空白字符 34 | static void skip_whitespace(JsonParser* parser) { 35 | while (parser->pos < parser->len && 36 | (parser->json[parser->pos] == ' ' || 37 | parser->json[parser->pos] == '\n' || 38 | parser->json[parser->pos] == '\r' || 39 | parser->json[parser->pos] == '\t')) { 40 | parser->pos++; 41 | } 42 | } 43 | 44 | // 解析字符串 45 | char* json_parse_string(JsonParser* parser) { 46 | if (parser->json[parser->pos] != '"') { 47 | set_error("预期字符串应以引号开始"); 48 | return NULL; 49 | } 50 | parser->pos++; 51 | 52 | size_t start = parser->pos; 53 | size_t len = 0; 54 | bool escaped = false; 55 | 56 | while (parser->pos < parser->len) { 57 | char c = parser->json[parser->pos]; 58 | if (escaped) { 59 | escaped = false; 60 | len++; 61 | } else if (c == '\\') { 62 | escaped = true; 63 | } else if (c == '"') { 64 | break; 65 | } else { 66 | len++; 67 | } 68 | parser->pos++; 69 | } 70 | 71 | if (parser->pos >= parser->len) { 72 | set_error("字符串未正确结束"); 73 | return NULL; 74 | } 75 | 76 | char* str = (char*)malloc(len + 1); 77 | if (!str) { 78 | set_error("内存分配失败"); 79 | return NULL; 80 | } 81 | 82 | size_t j = 0; 83 | escaped = false; 84 | for (size_t i = start; i < parser->pos; i++) { 85 | if (escaped) { 86 | switch (parser->json[i]) { 87 | case 'n': str[j++] = '\n'; break; 88 | case 'r': str[j++] = '\r'; break; 89 | case 't': str[j++] = '\t'; break; 90 | case '\\': str[j++] = '\\'; break; 91 | case '"': str[j++] = '"'; break; 92 | default: str[j++] = parser->json[i]; 93 | } 94 | escaped = false; 95 | } else if (parser->json[i] == '\\') { 96 | escaped = true; 97 | } else { 98 | str[j++] = parser->json[i]; 99 | } 100 | } 101 | str[j] = '\0'; 102 | parser->pos++; 103 | return str; 104 | } 105 | 106 | // 解析数字 107 | double json_parse_number(JsonParser* parser) { 108 | char* endptr; 109 | double num = strtod(parser->json + parser->pos, &endptr); 110 | if (endptr == parser->json + parser->pos) { 111 | set_error("无效的数字格式"); 112 | return 0; 113 | } 114 | parser->pos = endptr - parser->json; 115 | return num; 116 | } 117 | 118 | // 解析布尔值 119 | bool json_parse_bool(JsonParser* parser) { 120 | if (strncmp(parser->json + parser->pos, "true", 4) == 0) { 121 | parser->pos += 4; 122 | return true; 123 | } else if (strncmp(parser->json + parser->pos, "false", 5) == 0) { 124 | parser->pos += 5; 125 | return false; 126 | } 127 | set_error("无效的布尔值"); 128 | return false; 129 | } 130 | 131 | // 解析null 132 | void json_parse_null(JsonParser* parser) { 133 | if (strncmp(parser->json + parser->pos, "null", 4) == 0) { 134 | parser->pos += 4; 135 | return; 136 | } 137 | set_error("无效的null值"); 138 | } 139 | 140 | // 前向声明 141 | JsonValue* json_parse_value(JsonParser* parser); 142 | 143 | // 解析数组 144 | JsonArray* json_parse_array(JsonParser* parser) { 145 | if (parser->json[parser->pos] != '[') { 146 | set_error("预期数组应以'['开始"); 147 | return NULL; 148 | } 149 | parser->pos++; 150 | 151 | JsonArray* array = (JsonArray*)malloc(sizeof(JsonArray)); 152 | if (!array) { 153 | set_error("内存分配失败"); 154 | return NULL; 155 | } 156 | array->capacity = 8; 157 | array->size = 0; 158 | array->elements = (JsonValue**)malloc(sizeof(JsonValue*) * array->capacity); 159 | if (!array->elements) { 160 | free(array); 161 | set_error("内存分配失败"); 162 | return NULL; 163 | } 164 | 165 | skip_whitespace(parser); 166 | if (parser->json[parser->pos] == ']') { 167 | parser->pos++; 168 | return array; 169 | } 170 | 171 | while (parser->pos < parser->len) { 172 | JsonValue* value = json_parse_value(parser); 173 | if (!value) { 174 | // 错误信息已在parse_value中设置 175 | return NULL; 176 | } 177 | 178 | if (array->size >= array->capacity) { 179 | size_t new_capacity = array->capacity * 2; 180 | JsonValue** new_elements = (JsonValue**)realloc(array->elements, 181 | sizeof(JsonValue*) * new_capacity); 182 | if (!new_elements) { 183 | set_error("内存分配失败"); 184 | return NULL; 185 | } 186 | array->elements = new_elements; 187 | array->capacity = new_capacity; 188 | } 189 | 190 | array->elements[array->size++] = value; 191 | 192 | skip_whitespace(parser); 193 | if (parser->json[parser->pos] == ']') { 194 | parser->pos++; 195 | return array; 196 | } 197 | 198 | if (parser->json[parser->pos] != ',') { 199 | set_error("预期','或']'"); 200 | return NULL; 201 | } 202 | parser->pos++; 203 | skip_whitespace(parser); 204 | } 205 | 206 | set_error("数组未正确结束"); 207 | return NULL; 208 | } 209 | 210 | // 解析对象 211 | JsonObject* json_parse_object(JsonParser* parser) { 212 | if (parser->json[parser->pos] != '{') { 213 | set_error("预期对象应以'{'开始"); 214 | return NULL; 215 | } 216 | parser->pos++; 217 | 218 | JsonObject* object = (JsonObject*)malloc(sizeof(JsonObject)); 219 | if (!object) { 220 | set_error("内存分配失败"); 221 | return NULL; 222 | } 223 | memset(object, 0, sizeof(JsonObject)); 224 | object->capacity = 8; 225 | object->pairs = (JsonKeyValue*)malloc(sizeof(JsonKeyValue) * object->capacity); 226 | if (!object->pairs) { 227 | free(object); 228 | set_error("内存分配失败"); 229 | return NULL; 230 | } 231 | memset(object->pairs, 0, sizeof(JsonKeyValue) * object->capacity); 232 | 233 | skip_whitespace(parser); 234 | if (parser->json[parser->pos] == '}') { 235 | parser->pos++; 236 | return object; 237 | } 238 | 239 | while (parser->pos < parser->len) { 240 | skip_whitespace(parser); 241 | char* key = json_parse_string(parser); 242 | if (!key) return NULL; 243 | 244 | skip_whitespace(parser); 245 | if (parser->json[parser->pos] != ':') { 246 | set_error("预期':'"); 247 | free(key); 248 | return NULL; 249 | } 250 | parser->pos++; 251 | 252 | skip_whitespace(parser); 253 | JsonValue* value = json_parse_value(parser); 254 | if (!value) { 255 | free(key); 256 | return NULL; 257 | } 258 | 259 | if (object->size >= object->capacity) { 260 | size_t new_capacity = object->capacity * 2; 261 | JsonKeyValue* new_pairs = (JsonKeyValue*)realloc(object->pairs, 262 | sizeof(JsonKeyValue) * new_capacity); 263 | if (!new_pairs) { 264 | free(key); 265 | json_value_free(value); 266 | set_error("内存分配失败"); 267 | return NULL; 268 | } 269 | memset(new_pairs + object->capacity, 0, sizeof(JsonKeyValue) * (new_capacity - object->capacity)); 270 | object->pairs = new_pairs; 271 | object->capacity = new_capacity; 272 | } 273 | 274 | // 确保键值对正确存储 275 | object->pairs[object->size].key = strdup(key); 276 | object->pairs[object->size].value = value; 277 | object->size++; 278 | free(key); // 释放原始key,因为我们已经复制了它 279 | 280 | skip_whitespace(parser); 281 | if (parser->json[parser->pos] == '}') { 282 | parser->pos++; 283 | return object; 284 | } 285 | 286 | if (parser->json[parser->pos] != ',') { 287 | set_error("预期','或'}'"); 288 | return NULL; 289 | } 290 | parser->pos++; 291 | } 292 | 293 | set_error("对象未正确结束"); 294 | return NULL; 295 | } 296 | 297 | // 解析JSON值 298 | JsonValue* json_parse_value(JsonParser* parser) { 299 | skip_whitespace(parser); 300 | 301 | JsonValue* value = (JsonValue*)malloc(sizeof(JsonValue)); 302 | if (!value) { 303 | set_error("内存分配失败"); 304 | return NULL; 305 | } 306 | 307 | char c = parser->json[parser->pos]; 308 | switch (c) { 309 | case '"': 310 | value->type = JSON_STRING; 311 | value->value.string = json_parse_string(parser); 312 | if (!value->value.string) { 313 | free(value); 314 | return NULL; 315 | } 316 | break; 317 | 318 | case '{': 319 | value->type = JSON_OBJECT; 320 | value->value.object = json_parse_object(parser); 321 | if (!value->value.object) { 322 | free(value); 323 | return NULL; 324 | } 325 | break; 326 | 327 | case '[': 328 | value->type = JSON_ARRAY; 329 | value->value.array = json_parse_array(parser); 330 | if (!value->value.array) { 331 | free(value); 332 | return NULL; 333 | } 334 | break; 335 | 336 | case 't': 337 | case 'f': 338 | value->type = JSON_BOOL; 339 | value->value.boolean = json_parse_bool(parser); 340 | if (parser->pos >= parser->len) { 341 | free(value); 342 | return NULL; 343 | } 344 | break; 345 | 346 | case 'n': 347 | value->type = JSON_NULL; 348 | json_parse_null(parser); 349 | if (parser->pos >= parser->len) { 350 | free(value); 351 | return NULL; 352 | } 353 | break; 354 | 355 | default: 356 | if (c == '-' || isdigit(c)) { 357 | value->type = JSON_NUMBER; 358 | value->value.number = json_parse_number(parser); 359 | if (parser->pos >= parser->len) { 360 | free(value); 361 | return NULL; 362 | } 363 | } else { 364 | set_error("无效的JSON值"); 365 | free(value); 366 | return NULL; 367 | } 368 | } 369 | 370 | return value; 371 | } 372 | 373 | // 解析JSON字符串 374 | JsonValue* json_parse(const char* json) { 375 | JsonParser* parser = json_parser_create(json); 376 | if (!parser) return NULL; 377 | 378 | JsonValue* value = json_parse_value(parser); 379 | skip_whitespace(parser); 380 | 381 | if (parser->pos < parser->len) { 382 | set_error("JSON字符串后存在额外字符"); 383 | json_value_free(value); 384 | value = NULL; 385 | } 386 | 387 | json_parser_free(parser); 388 | return value; 389 | } 390 | 391 | // 释放解析器 392 | void json_parser_free(JsonParser* parser) { 393 | free(parser); 394 | } 395 | 396 | // 释放JSON值 397 | void json_value_free(JsonValue* value) { 398 | if (!value) return; 399 | 400 | switch (value->type) { 401 | case JSON_STRING: 402 | free(value->value.string); 403 | break; 404 | 405 | case JSON_ARRAY: 406 | if (value->value.array) { 407 | for (size_t i = 0; i < value->value.array->size; i++) { 408 | json_value_free(value->value.array->elements[i]); 409 | } 410 | free(value->value.array->elements); 411 | free(value->value.array); 412 | } 413 | break; 414 | 415 | case JSON_OBJECT: 416 | if (value->value.object) { 417 | for (size_t i = 0; i < value->value.object->size; i++) { 418 | free(value->value.object->pairs[i].key); 419 | json_value_free(value->value.object->pairs[i].value); 420 | } 421 | free(value->value.object->pairs); 422 | free(value->value.object); 423 | } 424 | break; 425 | 426 | default: 427 | break; 428 | } 429 | 430 | free(value); 431 | } 432 | 433 | // 获取值操作函数实现 434 | const char* json_value_get_string(JsonValue* value) { 435 | return (value && value->type == JSON_STRING) ? value->value.string : NULL; 436 | } 437 | 438 | double json_value_get_number(JsonValue* value) { 439 | return (value && value->type == JSON_NUMBER) ? value->value.number : 0.0; 440 | } 441 | 442 | bool json_value_get_bool(JsonValue* value) { 443 | return (value && value->type == JSON_BOOL) ? value->value.boolean : false; 444 | } 445 | 446 | JsonObject* json_value_get_object(JsonValue* value) { 447 | return (value && value->type == JSON_OBJECT) ? value->value.object : NULL; 448 | } 449 | 450 | JsonArray* json_value_get_array(JsonValue* value) { 451 | return (value && value->type == JSON_ARRAY) ? value->value.array : NULL; 452 | } -------------------------------------------------------------------------------- /test/test_json.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "unity.h" 5 | #include "json_builder.h" 6 | #include "json_parser.h" 7 | 8 | // 测试JSON构建器的基本功能 9 | void test_json_builder_basic() { 10 | JsonBuilder* builder = json_builder_create(1024); 11 | TEST_ASSERT_NOT_NULL(builder); 12 | 13 | // 测试创建简单对象 14 | TEST_ASSERT(json_builder_start_object(builder)); 15 | TEST_ASSERT(json_builder_add_string(builder, "name", "张三")); 16 | TEST_ASSERT(json_builder_add_number(builder, "age", 25)); 17 | TEST_ASSERT(json_builder_add_bool(builder, "is_student", true)); 18 | TEST_ASSERT(json_builder_add_null(builder, "address")); 19 | TEST_ASSERT(json_builder_end_object(builder)); 20 | 21 | const char* json_str = json_builder_get_string(builder); 22 | TEST_ASSERT_NOT_NULL(json_str); 23 | 24 | // 验证生成的JSON字符串 25 | const char* expected = "{\"name\":\"张三\",\"age\":25,\"is_student\":true,\"address\":null}"; 26 | TEST_ASSERT_EQUAL_STRING(expected, json_str); 27 | 28 | json_builder_free(builder); 29 | } 30 | 31 | // 测试嵌套对象和数组 32 | void test_json_complex_structure() { 33 | JsonBuilder* builder = json_builder_create(1024); 34 | TEST_ASSERT_NOT_NULL(builder); 35 | 36 | // 创建复杂的嵌套结构 37 | TEST_ASSERT(json_builder_start_object(builder)); 38 | 39 | // 添加嵌套对象 40 | TEST_ASSERT(json_builder_append(builder, "\"info\":{\"city\":\"北京\",\"district\":\"海淀\"},")); 41 | 42 | // 添加嵌套数组 43 | TEST_ASSERT(json_builder_append(builder, "\"scores\":[100,98.5,95.8],")); 44 | 45 | // 添加混合嵌套 46 | TEST_ASSERT(json_builder_append(builder, "\"details\":{\"subjects\":[\"数学\",\"物理\"],\"grades\":{\"term1\":95,\"term2\":97}}")); 47 | 48 | TEST_ASSERT(json_builder_end_object(builder)); 49 | 50 | const char* json_str = json_builder_get_string(builder); 51 | TEST_ASSERT_NOT_NULL(json_str); 52 | 53 | const char* expected = "{\"info\":{\"city\":\"北京\",\"district\":\"海淀\"},\"scores\":[100,98.5,95.8],\"details\":{\"subjects\":[\"数学\",\"物理\"],\"grades\":{\"term1\":95,\"term2\":97}}}"; 54 | TEST_ASSERT_EQUAL_STRING(expected, json_str); 55 | 56 | json_builder_free(builder); 57 | } 58 | 59 | // 测试特殊字符和转义 60 | void test_json_special_chars() { 61 | JsonBuilder* builder = json_builder_create(1024); 62 | TEST_ASSERT_NOT_NULL(builder); 63 | 64 | TEST_ASSERT(json_builder_start_object(builder)); 65 | TEST_ASSERT(json_builder_add_string(builder, "special", "\"引号\\反斜杠\n换行\r回车\t制表符")); 66 | TEST_ASSERT(json_builder_add_string(builder, "unicode", "\u4F60\u597D")); 67 | TEST_ASSERT(json_builder_end_object(builder)); 68 | 69 | const char* json_str = json_builder_get_string(builder); 70 | TEST_ASSERT_NOT_NULL(json_str); 71 | 72 | const char* expected = "{\"special\":\"\\\"引号\\\\反斜杠\\n换行\\r回车\\t制表符\",\"unicode\":\"你好\"}"; 73 | TEST_ASSERT_EQUAL_STRING(expected, json_str); 74 | 75 | json_builder_free(builder); 76 | } 77 | 78 | // 测试数字格式 79 | void test_json_numbers() { 80 | JsonBuilder* builder = json_builder_create(1024); 81 | TEST_ASSERT_NOT_NULL(builder); 82 | 83 | TEST_ASSERT(json_builder_start_object(builder)); 84 | TEST_ASSERT(json_builder_add_number(builder, "integer", 42)); 85 | TEST_ASSERT(json_builder_add_number(builder, "float", 3.14159)); 86 | TEST_ASSERT(json_builder_add_number(builder, "negative", -123.456)); 87 | TEST_ASSERT(json_builder_add_number(builder, "scientific", 1.23e-4)); 88 | TEST_ASSERT(json_builder_add_number(builder, "zero", 0)); 89 | TEST_ASSERT(json_builder_end_object(builder)); 90 | 91 | const char* json_str = json_builder_get_string(builder); 92 | TEST_ASSERT_NOT_NULL(json_str); 93 | 94 | // 注意:由于浮点数精度问题,这里使用近似比较 95 | JsonValue* value = json_parse(json_str); 96 | TEST_ASSERT_NOT_NULL(value); 97 | JsonObject* obj = json_value_get_object(value); 98 | TEST_ASSERT_NOT_NULL(obj); 99 | 100 | TEST_ASSERT_EQUAL_INT(42, (int)obj->pairs[0].value->value.number); 101 | TEST_ASSERT_FLOAT_WITHIN(0.00001, 3.14159, obj->pairs[1].value->value.number); 102 | TEST_ASSERT_FLOAT_WITHIN(0.00001, -123.456, obj->pairs[2].value->value.number); 103 | TEST_ASSERT_FLOAT_WITHIN(0.00001, 1.23e-4, obj->pairs[3].value->value.number); 104 | TEST_ASSERT_EQUAL_INT(0, (int)obj->pairs[4].value->value.number); 105 | 106 | json_value_free(value); 107 | json_builder_free(builder); 108 | } 109 | 110 | // 测试JSON构建器的数组功能 111 | void test_json_builder_array() { 112 | JsonBuilder* builder = json_builder_create(1024); 113 | TEST_ASSERT_NOT_NULL(builder); 114 | 115 | // 测试创建数组 116 | TEST_ASSERT(json_builder_start_array(builder)); 117 | TEST_ASSERT(json_builder_append(builder, "\"读书\",")); 118 | TEST_ASSERT(json_builder_append(builder, "\"音乐\",")); 119 | TEST_ASSERT(json_builder_append(builder, "\"编程\"")); 120 | TEST_ASSERT(json_builder_end_array(builder)); 121 | 122 | const char* json_str = json_builder_get_string(builder); 123 | TEST_ASSERT_NOT_NULL(json_str); 124 | 125 | // 验证生成的JSON数组 126 | const char* expected = "[\"读书\",\"音乐\",\"编程\"]"; 127 | TEST_ASSERT_EQUAL_STRING(expected, json_str); 128 | 129 | json_builder_free(builder); 130 | } 131 | 132 | // 测试JSON解析器的基本功能 133 | void test_json_parser_basic() { 134 | const char* json_str = "{\"name\":\"张三\",\"age\":25,\"is_student\":true,\"address\":null}"; 135 | JsonValue* value = json_parse(json_str); 136 | TEST_ASSERT_NOT_NULL(value); 137 | 138 | // 测试解析对象 139 | JsonObject* obj = json_value_get_object(value); 140 | TEST_ASSERT_NOT_NULL(obj); 141 | TEST_ASSERT_EQUAL_INT(4, obj->size); 142 | 143 | // 测试字符串值 144 | JsonValue* name = obj->pairs[0].value; 145 | TEST_ASSERT_EQUAL_STRING("张三", name->value.string); 146 | 147 | // 测试数字值 148 | JsonValue* age = obj->pairs[1].value; 149 | TEST_ASSERT_EQUAL_DOUBLE(25, age->value.number, 0.0001); 150 | 151 | // 测试布尔值 152 | JsonValue* is_student = obj->pairs[2].value; 153 | TEST_ASSERT(is_student->value.boolean); 154 | 155 | // 测试null值 156 | JsonValue* address = obj->pairs[3].value; 157 | TEST_ASSERT_EQUAL_INT(JSON_NULL, address->type); 158 | 159 | json_value_free(value); 160 | } 161 | 162 | // 测试JSON解析器的错误处理 163 | void test_json_parser_error() { 164 | // 测试无效的JSON 165 | const char* invalid_json = "{\"key\":}"; 166 | JsonValue* value = json_parse(invalid_json); 167 | TEST_ASSERT_NULL(value); 168 | TEST_ASSERT_NOT_NULL(json_get_error()); 169 | 170 | // 测试不完整的JSON 171 | const char* incomplete_json = "{\"key\":\"value"; 172 | value = json_parse(incomplete_json); 173 | TEST_ASSERT_NULL(value); 174 | TEST_ASSERT_NOT_NULL(json_get_error()); 175 | } 176 | 177 | // 测试空对象和空数组 178 | void test_json_empty_structures() { 179 | JsonBuilder* builder = json_builder_create(1024); 180 | TEST_ASSERT_NOT_NULL(builder); 181 | 182 | // 测试空对象 183 | TEST_ASSERT(json_builder_start_object(builder)); 184 | TEST_ASSERT(json_builder_end_object(builder)); 185 | const char* empty_obj = json_builder_get_string(builder); 186 | TEST_ASSERT_EQUAL_STRING("{}", empty_obj); 187 | 188 | // 重置构建器 189 | json_builder_free(builder); 190 | builder = json_builder_create(1024); 191 | TEST_ASSERT_NOT_NULL(builder); 192 | 193 | // 测试空数组 194 | TEST_ASSERT(json_builder_start_array(builder)); 195 | TEST_ASSERT(json_builder_end_array(builder)); 196 | const char* empty_array = json_builder_get_string(builder); 197 | TEST_ASSERT_EQUAL_STRING("[]", empty_array); 198 | 199 | json_builder_free(builder); 200 | } 201 | 202 | // 测试大数字和边界值 203 | void test_json_number_limits() { 204 | JsonBuilder* builder = json_builder_create(1024); 205 | TEST_ASSERT_NOT_NULL(builder); 206 | 207 | TEST_ASSERT(json_builder_start_object(builder)); 208 | TEST_ASSERT(json_builder_add_number(builder, "max_int", 2147483647)); 209 | TEST_ASSERT(json_builder_add_number(builder, "min_int", -2147483648)); 210 | TEST_ASSERT(json_builder_add_number(builder, "large_float", 1.7976931348623157e+100)); 211 | TEST_ASSERT(json_builder_add_number(builder, "small_float", 2.2250738585072014e-100)); 212 | TEST_ASSERT(json_builder_end_object(builder)); 213 | 214 | const char* json_str = json_builder_get_string(builder); 215 | TEST_ASSERT_NOT_NULL(json_str); 216 | 217 | JsonValue* value = json_parse(json_str); 218 | TEST_ASSERT_NOT_NULL(value); 219 | JsonObject* obj = json_value_get_object(value); 220 | TEST_ASSERT_NOT_NULL(obj); 221 | 222 | TEST_ASSERT_EQUAL_INT(2147483647, (int)obj->pairs[0].value->value.number); 223 | TEST_ASSERT_EQUAL_INT(-2147483648, (int)obj->pairs[1].value->value.number); 224 | TEST_ASSERT_FLOAT_WITHIN(1e+100, 1.7976931348623157e+100, obj->pairs[2].value->value.number); 225 | TEST_ASSERT_FLOAT_WITHIN(1e-100, 2.2250738585072014e-100, obj->pairs[3].value->value.number); 226 | 227 | json_value_free(value); 228 | json_builder_free(builder); 229 | } 230 | 231 | // 测试深层嵌套结构 232 | void test_json_deep_nesting() { 233 | JsonBuilder* builder = json_builder_create(1024); 234 | TEST_ASSERT_NOT_NULL(builder); 235 | 236 | // 创建深层嵌套的JSON结构 237 | TEST_ASSERT(json_builder_start_object(builder)); 238 | TEST_ASSERT(json_builder_append(builder, "\"level1\":")); 239 | TEST_ASSERT(json_builder_start_object(builder)); 240 | TEST_ASSERT(json_builder_append(builder, "\"level2\":")); 241 | TEST_ASSERT(json_builder_start_object(builder)); 242 | TEST_ASSERT(json_builder_append(builder, "\"level3\":")); 243 | TEST_ASSERT(json_builder_start_object(builder)); 244 | TEST_ASSERT(json_builder_append(builder, "\"level4\":")); 245 | TEST_ASSERT(json_builder_start_object(builder)); 246 | TEST_ASSERT(json_builder_append(builder, "\"level5\":")); 247 | TEST_ASSERT(json_builder_start_object(builder)); 248 | TEST_ASSERT(json_builder_add_number(builder, "value", 42)); 249 | TEST_ASSERT(json_builder_end_object(builder)); 250 | TEST_ASSERT(json_builder_append(builder, ",")); 251 | TEST_ASSERT(json_builder_end_object(builder)); 252 | TEST_ASSERT(json_builder_append(builder, ",")); 253 | TEST_ASSERT(json_builder_end_object(builder)); 254 | TEST_ASSERT(json_builder_append(builder, ",")); 255 | TEST_ASSERT(json_builder_end_object(builder)); 256 | TEST_ASSERT(json_builder_append(builder, ",")); 257 | TEST_ASSERT(json_builder_end_object(builder)); 258 | TEST_ASSERT(json_builder_append(builder, ",")); 259 | TEST_ASSERT(json_builder_end_object(builder)); 260 | 261 | const char* json_str = json_builder_get_string(builder); 262 | printf("%s\n", json_str); 263 | TEST_ASSERT_NOT_NULL(json_str); 264 | 265 | JsonValue* value = json_parse(json_str); 266 | TEST_ASSERT_NOT_NULL(value); 267 | 268 | // 验证深层嵌套的值 269 | JsonObject* obj1 = json_value_get_object(value); 270 | TEST_ASSERT_NOT_NULL(obj1); 271 | JsonValue* val1 = obj1->pairs[0].value; 272 | TEST_ASSERT_NOT_NULL(val1); 273 | 274 | JsonObject* obj2 = json_value_get_object(val1); 275 | TEST_ASSERT_NOT_NULL(obj2); 276 | JsonValue* val2 = obj2->pairs[0].value; 277 | TEST_ASSERT_NOT_NULL(val2); 278 | 279 | JsonObject* obj3 = json_value_get_object(val2); 280 | TEST_ASSERT_NOT_NULL(obj3); 281 | JsonValue* val3 = obj3->pairs[0].value; 282 | TEST_ASSERT_NOT_NULL(val3); 283 | 284 | JsonObject* obj4 = json_value_get_object(val3); 285 | TEST_ASSERT_NOT_NULL(obj4); 286 | JsonValue* val4 = obj4->pairs[0].value; 287 | TEST_ASSERT_NOT_NULL(val4); 288 | 289 | JsonObject* obj5 = json_value_get_object(val4); 290 | TEST_ASSERT_NOT_NULL(obj5); 291 | JsonValue* val5 = obj5->pairs[0].value; 292 | TEST_ASSERT_NOT_NULL(val5); 293 | 294 | // The innermost object has a key "value" with value 42 295 | JsonObject* innerObj = json_value_get_object(val5); 296 | TEST_ASSERT_NOT_NULL(innerObj); 297 | TEST_ASSERT_EQUAL_STRING("value", innerObj->pairs[0].key); 298 | TEST_ASSERT_EQUAL_INT(42, (int)innerObj->pairs[0].value->value.number); 299 | 300 | json_value_free(value); 301 | json_builder_free(builder); 302 | } 303 | 304 | // 主测试函数 305 | int main() { 306 | // 设置控制台为UTF-8编码 307 | set_console_utf8(); 308 | 309 | // 初始化测试框架 310 | unity_begin(); 311 | 312 | // 运行所有测试用例 313 | RUN_TEST(test_json_builder_basic); 314 | RUN_TEST(test_json_builder_array); 315 | RUN_TEST(test_json_complex_structure); 316 | RUN_TEST(test_json_special_chars); 317 | RUN_TEST(test_json_numbers); 318 | RUN_TEST(test_json_parser_basic); 319 | RUN_TEST(test_json_parser_error); 320 | RUN_TEST(test_json_empty_structures); 321 | RUN_TEST(test_json_number_limits); 322 | RUN_TEST(test_json_deep_nesting); 323 | 324 | // 完成测试并显示结果 325 | unity_end(); 326 | 327 | return failed_tests; 328 | } -------------------------------------------------------------------------------- /test/unity.c: -------------------------------------------------------------------------------- 1 | #include "unity.h" 2 | 3 | // 测试计数器 4 | int total_tests = 0; 5 | int failed_tests = 0; 6 | 7 | // 测试初始化 8 | void unity_begin(void) { 9 | total_tests = 0; 10 | failed_tests = 0; 11 | printf("\n开始运行测试..."); 12 | } 13 | 14 | // 测试清理和报告 15 | void unity_end(void) { 16 | printf("\n测试完成。总共运行 %d 个测试,%d 个失败。\n", 17 | total_tests, failed_tests); 18 | } -------------------------------------------------------------------------------- /test/unity.h: -------------------------------------------------------------------------------- 1 | #ifndef UNITY_H 2 | #define UNITY_H 3 | 4 | #include 5 | #include 6 | 7 | // 测试计数器 8 | extern int total_tests; 9 | extern int failed_tests; 10 | 11 | // 测试宏 12 | #define TEST_ASSERT(condition) do { \ 13 | total_tests++; \ 14 | if (!(condition)) { \ 15 | failed_tests++; \ 16 | printf("❌ 断言失败: %s (行 %d)\n", #condition, __LINE__); \ 17 | } else { \ 18 | printf("✓ 测试通过: %s\n", #condition); \ 19 | } \ 20 | } while (0) 21 | 22 | #define TEST_ASSERT_EQUAL_STRING(expected, actual) do { \ 23 | total_tests++; \ 24 | if (strcmp(expected, actual) != 0) { \ 25 | failed_tests++; \ 26 | printf("❌ 字符串不匹配:\n 期望: %s\n 实际: %s\n (行 %d)\n", expected, actual, __LINE__); \ 27 | } else { \ 28 | printf("✓ 字符串匹配: %s\n", expected); \ 29 | } \ 30 | } while (0) 31 | 32 | #define TEST_ASSERT_EQUAL_INT(expected, actual) do { \ 33 | total_tests++; \ 34 | if (expected != actual) { \ 35 | failed_tests++; \ 36 | printf("❌ 整数不匹配:\n 期望: %d\n 实际: %d\n (行 %d)\n", expected, actual, __LINE__); \ 37 | } else { \ 38 | printf("✓ 整数匹配: %d\n", expected); \ 39 | } \ 40 | } while (0) 41 | 42 | #define TEST_ASSERT_EQUAL_DOUBLE(expected, actual, epsilon) do { \ 43 | total_tests++; \ 44 | if (fabs(expected - actual) > epsilon) { \ 45 | failed_tests++; \ 46 | printf("❌ 浮点数不匹配:\n 期望: %f\n 实际: %f\n (行 %d)\n", expected, actual, __LINE__); \ 47 | } else { \ 48 | printf("✓ 浮点数匹配: %f\n", expected); \ 49 | } \ 50 | } while (0) 51 | 52 | #define TEST_ASSERT_FLOAT_WITHIN(delta, expected, actual) do { \ 53 | total_tests++; \ 54 | if (fabs(expected - actual) > delta) { \ 55 | failed_tests++; \ 56 | printf("❌ 浮点数超出允许范围:\n 期望: %f\n 实际: %f\n 允许误差: %f\n (行 %d)\n", expected, actual, delta, __LINE__); \ 57 | } else { \ 58 | printf("✓ 浮点数在允许范围内: %f (误差: %f)\n", actual, fabs(expected - actual)); \ 59 | } \ 60 | } while (0) 61 | 62 | #define TEST_ASSERT_NULL(pointer) do { \ 63 | total_tests++; \ 64 | if (pointer != NULL) { \ 65 | failed_tests++; \ 66 | printf("❌ 指针不为NULL (行 %d)\n", __LINE__); \ 67 | } else { \ 68 | printf("✓ 指针为NULL\n"); \ 69 | } \ 70 | } while (0) 71 | 72 | #define TEST_ASSERT_NOT_NULL(pointer) do { \ 73 | total_tests++; \ 74 | if (pointer == NULL) { \ 75 | failed_tests++; \ 76 | printf("❌ 指针为NULL (行 %d)\n", __LINE__); \ 77 | } else { \ 78 | printf("✓ 指针不为NULL\n"); \ 79 | } \ 80 | } while (0) 81 | 82 | // 测试运行器 83 | #define RUN_TEST(test_func) do { \ 84 | printf("\n运行测试: %s\n", #test_func); \ 85 | test_func(); \ 86 | } while (0) 87 | 88 | // 测试初始化和清理 89 | void unity_begin(void); 90 | void unity_end(void); 91 | 92 | #endif // UNITY_H --------------------------------------------------------------------------------