深入理解yyjson库:API设计与使用指南
yyjson是一个高性能的C语言JSON库,本文将从技术角度深入解析其API设计理念和使用方法,帮助开发者更好地理解和使用这个库。
API设计哲学
yyjson的API设计遵循了几个核心原则:
-
一致性:所有公共函数和结构体都以
yyjson_
作为前缀,常量以YYJSON_
作为前缀,这种命名约定提高了代码的可读性和一致性。 -
不可变与可变分离:
- 不可变数据结构:
yyjson_doc
和yyjson_val
- 可变数据结构:
yyjson_mut_doc
和yyjson_mut_val
- 不可变数据结构:
这种分离设计使得API更加清晰,同时也优化了性能。读取JSON时返回不可变结构,构建JSON时使用可变结构。
- 内存管理:文档对象负责管理其包含的所有JSON值和字符串的内存,简化了内存管理。
字符串处理策略
yyjson在字符串处理上提供了灵活的选项:
- 空终止符处理:
- 常规函数要求字符串以空字符结尾
- 以
n
结尾的函数可以处理不含空终止符的字符串
bool yyjson_equals_str(yyjson_val *val, const char *str); // 需要空终止符
bool yyjson_equals_strn(yyjson_val *val, const char *str, size_t len); // 不需要空终止符
- 字符串所有权:
- 默认情况下,yyjson会引用字符串而不是复制它们(提高性能)
- 当字符串可能被修改时,应使用带有
cpy
的函数来创建副本
yyjson_mut_val *yyjson_mut_str(yyjson_mut_doc *doc, const char *str); // 仅引用
yyjson_mut_val *yyjson_mut_strcpy(yyjson_mut_doc *doc, const char *str); // 创建副本
JSON读取详解
yyjson提供了四种读取JSON的方式,满足不同场景需求:
1. 从字符串读取
yyjson_doc *doc = yyjson_read("[1,2,3]", 7, 0);
2. 从文件读取
yyjson_doc *doc = yyjson_read_file("/tmp/test.json", 0, NULL, NULL);
3. 从文件指针读取
FILE *fp = fdopen(fd, "rb");
yyjson_doc *doc = yyjson_read_fp(fp, 0, NULL, NULL);
4. 带选项读取
yyjson_doc *doc = yyjson_read_opts(data, len, flags, allocator, &error);
错误处理机制
当读取失败时,可以通过yyjson_read_err
结构获取详细错误信息:
yyjson_read_err err;
yyjson_doc *doc = yyjson_read_opts(data, len, 0, NULL, &err);
if (!doc) {
printf("错误: %s (代码: %u, 位置: %lu)\n", err.msg, err.code, err.pos);
}
还可以定位错误的具体行列位置:
size_t line, col;
yyjson_locate_pos(data, len, err.pos, &line, &col, NULL);
printf("错误位于第%lu行, 第%lu列\n", line, col);
JSON写入详解
yyjson同样提供了多种写入JSON的方式:
1. 写入字符串
char *json = yyjson_write(doc, YYJSON_WRITE_PRETTY, NULL);
free(json);
2. 写入文件
bool success = yyjson_write_file("/tmp/output.json", doc, 0, NULL, NULL);
3. 写入文件指针
FILE *fp = fopen("/tmp/output.json", "wb");
bool success = yyjson_write_fp(fp, doc, 0, NULL, NULL);
fclose(fp);
4. 带选项写入
yyjson_write_err err;
char *json = yyjson_write_opts(doc, flags, allocator, &len, &err);
高级特性
读取标志(Read Flags)
yyjson提供了一系列读取标志来控制解析行为:
YYJSON_READ_INSITU
:原地解析,提高性能但需要额外填充YYJSON_READ_STOP_WHEN_DONE
:解析完第一个JSON对象后停止YYJSON_READ_ALLOW_COMMENTS
:允许注释YYJSON_READ_ALLOW_TRAILING_COMMAS
:允许末尾逗号YYJSON_READ_ALLOW_INF_AND_NAN
:允许Infinity和NaNYYJSON_READ_NUMBER_AS_RAW
:将数字作为原始字符串读取YYJSON_READ_BIGNUM_AS_RAW
:将大数字作为原始字符串读取
写入标志(Write Flags)
写入时也有多种标志控制输出格式:
YYJSON_WRITE_PRETTY
:美化输出(带缩进和换行)YYJSON_WRITE_ESCAPE_UNICODE
:转义Unicode字符YYJSON_WRITE_ESCAPE_SLASHES
:转义斜杠YYJSON_WRITE_ALLOW_INF_AND_NAN
:允许写入Infinity和NaN
最佳实践
- 性能敏感场景:考虑使用
YYJSON_READ_INSITU
标志,但要注意内存安全 - 大数据处理:使用
YYJSON_READ_STOP_WHEN_DONE
处理流式JSON - 特殊数字处理:使用
YYJSON_READ_BIGNUM_AS_RAW
处理大数字 - 内存受限环境:使用自定义内存分配器
通过深入理解yyjson的API设计和使用方法,开发者可以更高效地处理JSON数据,同时根据具体需求选择最适合的配置选项。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考