yyjson 0.11.0
A high performance C JSON library.
Loading...
Searching...
No Matches
Introduction

Build Codecov License Version Packaging status

A high performance JSON library written in ANSI C.

Features

  • Fast: can read or write gigabytes per second JSON data on modern CPUs.
  • Portable: complies with ANSI C (C89) for cross-platform compatibility.
  • Strict: complies with RFC 8259 JSON standard, ensuring strict number format and UTF-8 validation.
  • Extendable: offers options to allow comments, trailing commas, NaN/Inf, and custom memory allocator.
  • Accuracy: can accurately read and write int64, uint64, and double numbers.
  • Flexible: supports unlimited JSON nesting levels, \u0000 characters, and non null-terminated strings.
  • Manipulation: supports querying and modifying using JSON Pointer, JSON Patch and JSON Merge Patch.
  • Developer-Friendly: easy integration with only one h and one c file.

Limitations

  • An array or object is stored as a data structure such as linked list, which makes accessing elements by index or key slower than using an iterator.
  • Duplicate keys are allowed in an object, and the order of the keys is preserved.
  • JSON parsing result is immutable, requiring a mutable copy for modification.

Performance

Benchmark project and dataset: yyjson_benchmark

The simdjson's new On Demand API is faster if most JSON fields are known at compile-time. This benchmark project only checks the DOM API, a new benchmark will be added later.

AWS EC2 (AMD EPYC 7R32, gcc 9.3)

twitter.json parse (GB/s) stringify (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)

twitter.json parse (GB/s) stringify (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

More benchmark reports with interactive charts (update 2020-12-12)

Platform CPU Compiler OS Report
Intel NUC 8i5 Core i5-8259U msvc 2019 Windows 10 2004 Charts
Intel NUC 8i5 Core i5-8259U clang 10.0 Ubuntu 20.04 Charts
Intel NUC 8i5 Core i5-8259U gcc 9.3 Ubuntu 20.04 Charts
AWS EC2 c5a.large AMD EPYC 7R32 gcc 9.3 Ubuntu 20.04 Charts
AWS EC2 t4g.medium Graviton2 (ARM64) gcc 9.3 Ubuntu 20.04 Charts
Apple iPhone 12 Pro A14 (ARM64) clang 12.0 iOS 14 Charts

For better performance, yyjson prefers:

  • A modern processor with:
    • high instruction level parallelism
    • excellent branch predictor
    • low penalty for misaligned memory access
  • A modern compiler with good optimizer (e.g. clang)

Sample Code

Read JSON string

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);
// 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_arr_foreach(hits, idx, max, hit) {
printf("hit%d: %d\n", (int)idx, (int)yyjson_get_int(hit));
}
// Free the doc
// All functions accept NULL input, and return NULL on error.
yyjson_api_inline yyjson_val * yyjson_obj_get(yyjson_val *obj, const char *key)
Definition yyjson.h:5425
yyjson_api_inline int yyjson_get_int(yyjson_val *val)
Definition yyjson.h:5194
#define yyjson_arr_foreach(arr, idx, max, val)
Definition yyjson.h:1988
yyjson_api_inline const char * yyjson_get_str(yyjson_val *val)
Definition yyjson.h:5206
yyjson_api_inline yyjson_val * yyjson_doc_get_root(yyjson_doc *doc)
Definition yyjson.h:5060
yyjson_api_inline void yyjson_doc_free(yyjson_doc *doc)
Definition yyjson.h:5072
yyjson_api_inline size_t yyjson_get_len(yyjson_val *val)
Definition yyjson.h:5210
yyjson_api_inline yyjson_doc * yyjson_read(const char *dat, size_t len, yyjson_read_flag flg)
Definition yyjson.h:940
Definition yyjson.h:4712
Definition yyjson.h:4707

Write JSON string

// Create a mutable doc
// 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_api_inline bool yyjson_mut_obj_add_val(yyjson_mut_doc *doc, yyjson_mut_val *obj, const char *key, yyjson_mut_val *val)
Definition yyjson.h:7239
yyjson_api_inline yyjson_mut_val * yyjson_mut_arr_with_sint32(yyjson_mut_doc *doc, const int32_t *vals, size_t count)
Definition yyjson.h:6206
yyjson_api_inline bool yyjson_mut_obj_add_int(yyjson_mut_doc *doc, yyjson_mut_val *obj, const char *key, int64_t val)
Definition yyjson.h:7143
yyjson_api_inline yyjson_mut_val * yyjson_mut_obj(yyjson_mut_doc *doc)
Definition yyjson.h:6812
yyjson_api void yyjson_mut_doc_free(yyjson_mut_doc *doc)
yyjson_api_inline char * yyjson_mut_write(const yyjson_mut_doc *doc, yyjson_write_flag flg, size_t *len)
Definition yyjson.h:1433
yyjson_api_inline void yyjson_mut_doc_set_root(yyjson_mut_doc *doc, yyjson_mut_val *root)
Definition yyjson.h:5647
yyjson_api_inline bool yyjson_mut_obj_add_str(yyjson_mut_doc *doc, yyjson_mut_val *obj, const char *key, const char *val)
Definition yyjson.h:7171
yyjson_api yyjson_mut_doc * yyjson_mut_doc_new(const yyjson_alc *alc)
Definition yyjson.h:5580
Definition yyjson.h:5532

Read JSON file with options

// Read JSON file, allowing comments and trailing commas
yyjson_doc *doc = yyjson_read_file("/tmp/config.json", flg, NULL, &err);
// Iterate over the root object
if (doc) {
yyjson_obj_iter_init(obj, &iter);
yyjson_val *key, *val;
while ((key = yyjson_obj_iter_next(&iter))) {
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
static const yyjson_read_flag YYJSON_READ_ALLOW_TRAILING_COMMAS
Definition yyjson.h:754
yyjson_api_inline bool yyjson_obj_iter_init(yyjson_val *obj, yyjson_obj_iter *iter)
Definition yyjson.h:5450
yyjson_api_inline yyjson_val * yyjson_obj_iter_get_val(yyjson_val *key)
Definition yyjson.h:5483
uint32_t yyjson_read_flag
Definition yyjson.h:727
yyjson_api_inline const char * yyjson_get_type_desc(yyjson_val *val)
Definition yyjson.h:5161
yyjson_read_code code
Definition yyjson.h:839
yyjson_api_inline yyjson_val * yyjson_obj_iter_next(yyjson_obj_iter *iter)
Definition yyjson.h:5473
yyjson_api yyjson_doc * yyjson_read_file(const char *path, yyjson_read_flag flg, const yyjson_alc *alc, yyjson_read_err *err)
size_t pos
Definition yyjson.h:843
const char * msg
Definition yyjson.h:841
static const yyjson_read_flag YYJSON_READ_ALLOW_COMMENTS
Definition yyjson.h:757
Definition yyjson.h:2056
Definition yyjson.h:837

Write JSON file with options

// Read the JSON file as a mutable doc
yyjson_doc *idoc = yyjson_read_file("/tmp/config.json", 0, NULL, NULL);
// Remove null values in root object
yyjson_mut_val *key, *val;
while ((key = yyjson_mut_obj_iter_next(&iter))) {
if (yyjson_mut_is_null(val)) {
}
}
// Write the json pretty, escape unicode
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_api yyjson_mut_doc * yyjson_doc_mut_copy(yyjson_doc *doc, const yyjson_alc *alc)
yyjson_api_inline bool yyjson_mut_is_null(yyjson_mut_val *val)
Definition yyjson.h:5662
const char * msg
Definition yyjson.h:1225
yyjson_api_inline yyjson_mut_val * yyjson_mut_obj_iter_next(yyjson_mut_obj_iter *iter)
Definition yyjson.h:6746
yyjson_api_inline yyjson_mut_val * yyjson_mut_obj_iter_remove(yyjson_mut_obj_iter *iter)
Definition yyjson.h:6763
yyjson_api_inline yyjson_mut_val * yyjson_mut_doc_get_root(yyjson_mut_doc *doc)
Definition yyjson.h:5643
yyjson_api_inline yyjson_mut_val * yyjson_mut_obj_iter_get_val(yyjson_mut_val *key)
Definition yyjson.h:6758
static const yyjson_write_flag YYJSON_WRITE_ESCAPE_UNICODE
Definition yyjson.h:1142
yyjson_api bool yyjson_mut_write_file(const char *path, const yyjson_mut_doc *doc, yyjson_write_flag flg, const yyjson_alc *alc, yyjson_write_err *err)
yyjson_api_inline bool yyjson_mut_obj_iter_init(yyjson_mut_val *obj, yyjson_mut_obj_iter *iter)
Definition yyjson.h:6721
yyjson_write_code code
Definition yyjson.h:1223
static const yyjson_write_flag YYJSON_WRITE_PRETTY
Definition yyjson.h:1139
uint32_t yyjson_write_flag
Definition yyjson.h:1129
Definition yyjson.h:3479
Definition yyjson.h:1221

Documentation

The latest (unreleased) documentation can be accessed in the doc directory. The pre-generated Doxygen HTML for the release version can be viewed here:

Packaging status

Packaging status

Built With yyjson

A non-exhaustive list of projects that expose yyjson to other languages or use yyjson internally for a major feature. If you have a project that uses yyjson, feel free to open a PR to add it to this list.

Project Language Description
py_yyjson Python Python bindings for yyjson
orjson Python JSON library for Python with an optional yyjson backend
cpp-yyjson C++ C++ JSON library with a yyjson backend
reflect-cpp C++ C++ library for serialization through automated field name retrieval from structs
yyjsonr R R binding for yyjson
Ananda Swift JSON model decoding based on yyjson
duckdb C++ DuckDB is an in-process SQL OLAP Database Management System
fastfetch C A neofetch-like tool for fetching system information and displaying them in a pretty way
Zrythm C Digital Audio Workstation that uses yyjson to serialize JSON project files
bemorehuman C Recommendation engine with a focus on uniqueness of the person receiving the rec
mruby-yyjson mruby Efficient JSON parsing and serialization library for mruby using yyjson
YYJSON.jl Julia Julia bindings for yyjson

TODO for v1.0

  • [x] Add documentation page.
  • [x] Add GitHub workflow for CI and codecov.
  • [x] Add more tests: valgrind, sanitizer, fuzzing.
  • [x] Support JSON Pointer to query and modify JSON.
  • [x] Add RAW type for JSON reader and writer.
  • [x] Add option to limit real number output precision.
  • [ ] Add option to support JSON5 (if feasible).
  • [ ] Add functions to diff two JSON documents.
  • [ ] Add documentation on performance optimizations.
  • [ ] Ensure ABI stability.

License

This project is released under the MIT license.