简介

Build Codecov License Version Packaging status

一个用 ANSI C 编写的高性能 JSON 库。

特性

局限性

性能

基准测试项目和数据集:yyjson_benchmark

如果大多数 JSON 字段在编译时已知,simdjson 的新 On Demand API 会更快。 此基准测试项目仅检查 DOM API,稍后将添加新的基准测试。

AWS EC2 (AMD EPYC 7R32, gcc 9.3)

ec2_chart

twitter.json 解析 (GB/s) 字符串化 (GB/s)
yyjson(insitu) 1.80 1.51
yyjson 1.72 1.42
simdjson 1.52 0.61
sajson 1.16
rapidjson(insitu) 0.77
rapidjson(utf8) 0.26 0.39
cjson 0.32 0.17
jansson 0.05 0.11

iPhone (Apple A14, clang 12)

a14_chart

twitter.json 解析 (GB/s) 字符串化 (GB/s)
yyjson(insitu) 3.51 2.41
yyjson 2.39 2.01
simdjson 2.19 0.80
sajson 1.74
rapidjson(insitu) 0.75
rapidjson(utf8) 0.30 0.58
cjson 0.48 0.33
jansson 0.09 0.24

更多具有交互式图表的基准测试报告(更新于 2020-12-12)

平台 CPU 编译器 操作系统 报告
Intel NUC 8i5 Core i5-8259U msvc 2019 Windows 10 2004 图表
Intel NUC 8i5 Core i5-8259U clang 10.0 Ubuntu 20.04 图表
Intel NUC 8i5 Core i5-8259U gcc 9.3 Ubuntu 20.04 图表
AWS EC2 c5a.large AMD EPYC 7R32 gcc 9.3 Ubuntu 20.04 图表
AWS EC2 t4g.medium Graviton2 (ARM64) gcc 9.3 Ubuntu 20.04 图表
Apple iPhone 12 Pro A14 (ARM64) clang 12.0 iOS 14 图表

为了获得更好的性能,yyjson 优先选择:

示例代码

读取 JSON 字符串

const char *json = "{\"name\":\"Mash\",\"star\":4,\"hits\":[2,2,1,3]}";

// Read JSON and get root
yyjson_doc *doc = yyjson_read(json, strlen(json), 0);
yyjson_val *root = yyjson_doc_get_root(doc);

// Get root["name"]
yyjson_val *name = yyjson_obj_get(root, "name");
printf("name: %s\n", yyjson_get_str(name));
printf("name length:%d\n", (int)yyjson_get_len(name));

// Get root["star"]
yyjson_val *star = yyjson_obj_get(root, "star");
printf("star: %d\n", (int)yyjson_get_int(star));

// Get root["hits"], iterate over the array
yyjson_val *hits = yyjson_obj_get(root, "hits");
size_t idx, max;
yyjson_val *hit;
yyjson_arr_foreach(hits, idx, max, hit) {
    printf("hit%d: %d\n", (int)idx, (int)yyjson_get_int(hit));
}

// Free the doc
yyjson_doc_free(doc);

// All functions accept NULL input, and return NULL on error.

写入 JSON 字符串

// Create a mutable doc
yyjson_mut_doc *doc = yyjson_mut_doc_new(NULL);
yyjson_mut_val *root = yyjson_mut_obj(doc);
yyjson_mut_doc_set_root(doc, root);

// Set root["name"] and root["star"]
yyjson_mut_obj_add_str(doc, root, "name", "Mash");
yyjson_mut_obj_add_int(doc, root, "star", 4);

// Set root["hits"] with an array
int hits_arr[] = {2, 2, 1, 3};
yyjson_mut_val *hits = yyjson_mut_arr_with_sint32(doc, hits_arr, 4);
yyjson_mut_obj_add_val(doc, root, "hits", hits);

// To string, minified
const char *json = yyjson_mut_write(doc, 0, NULL);
if (json) {
    printf("json: %s\n", json); // {"name":"Mash","star":4,"hits":[2,2,1,3]}
    free((void *)json);
}

// Free the doc
yyjson_mut_doc_free(doc);

使用选项读取 JSON 文件

// Read JSON file, allowing comments and trailing commas
yyjson_read_flag flg = YYJSON_READ_ALLOW_COMMENTS | YYJSON_READ_ALLOW_TRAILING_COMMAS;
yyjson_read_err err;
yyjson_doc *doc = yyjson_read_file("/tmp/config.json", flg, NULL, &err);

// Iterate over the root object
if (doc) {
    yyjson_val *obj = yyjson_doc_get_root(doc);
    yyjson_obj_iter iter;
    yyjson_obj_iter_init(obj, &iter);
    yyjson_val *key, *val;
    while ((key = yyjson_obj_iter_next(&iter))) {
        val = yyjson_obj_iter_get_val(key);
        printf("%s: %s\n", yyjson_get_str(key), yyjson_get_type_desc(val));
    }
} else {
    printf("read error (%u): %s at position: %ld\n", err.code, err.msg, err.pos);
}

// Free the doc
yyjson_doc_free(doc);

使用选项写入 JSON 文件

// Read the JSON file as a mutable doc
yyjson_doc *idoc = yyjson_read_file("/tmp/config.json", 0, NULL, NULL);
yyjson_mut_doc *doc = yyjson_doc_mut_copy(idoc, NULL);
yyjson_mut_val *obj = yyjson_mut_doc_get_root(doc);

// Remove null values in root object
yyjson_mut_obj_iter iter;
yyjson_mut_obj_iter_init(obj, &iter);
yyjson_mut_val *key, *val;
while ((key = yyjson_mut_obj_iter_next(&iter))) {
    val = yyjson_mut_obj_iter_get_val(key);
    if (yyjson_mut_is_null(val)) {
        yyjson_mut_obj_iter_remove(&iter);
    }
}

// Write the json pretty, escape unicode
yyjson_write_flag flg = YYJSON_WRITE_PRETTY | YYJSON_WRITE_ESCAPE_UNICODE;
yyjson_write_err err;
yyjson_mut_write_file("/tmp/config.json", doc, flg, NULL, &err);
if (err.code) {
    printf("write error (%u): %s\n", err.code, err.msg);
}

// Free the doc
yyjson_doc_free(idoc);
yyjson_mut_doc_free(doc);

文档

最新的(未发布的)文档可以在 doc 目录中找到。发布版本的预生成 Doxygen HTML 可在此处查看

打包状态

Packaging status

使用 yyjson 构建的项目

以下是一个非详尽的列表,列出了将 yyjson 暴露给其他语言的项目,或者在内部使用 yyjson 来实现主要功能的项目。如果您有一个使用 yyjson 的项目,请随时打开 PR 将其添加到此列表中。

项目 语言 描述
py_yyjson Python yyjson 的 Python 绑定
orjson Python Python 的 JSON 库,具有可选的 yyjson 后端
cpp-yyjson C++ 具有 yyjson 后端的 C++ JSON 库
reflect-cpp C++ C++ 库,用于通过从结构体自动检索字段名称来进行序列化
yyjsonr R yyjson 的 R 绑定
Ananda Swift 基于 yyjson 的 JSON 模型解码
duckdb C++ DuckDB 是一个进程内的 SQL OLAP 数据库管理系统
fastfetch C 一个类似 neofetch 的工具,用于获取系统信息并以漂亮的方式显示它们
Zrythm C 数字音频工作站,使用 yyjson 序列化 JSON 项目文件
bemorehuman C 推荐引擎,专注于接收推荐的人的独特性
mruby-yyjson mruby 使用 yyjson 的 mruby 的高效 JSON 解析和序列化库
YYJSON.jl Julia yyjson 的 Julia 绑定

v1.0 的 TODO 列表

许可证

此项目已在 MIT 许可下发布。