├── .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 |

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 |
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
--------------------------------------------------------------------------------