Top Related Projects
Parsing gigabytes of JSON per second : used by Facebook/Meta Velox, the Node.js runtime, ClickHouse, WatermelonDB, Apache Doris, Milvus, StarRocks
A fast JSON parser/generator for C++ with both SAX/DOM style API
JSON for Modern C++
C/C++ JSON parser/generator benchmark
Jsmn is a world fastest JSON parser/tokenizer. This is the official repo replacing the old one at Bitbucket
Quick Overview
yyjson is a high-performance JSON library written in ANSI C. It provides fast JSON parsing and serialization capabilities, with a focus on speed and efficiency. The library is designed to be lightweight, easy to use, and suitable for various platforms and applications.
Pros
- Extremely fast JSON parsing and serialization
- Low memory usage and zero dependencies
- Supports both UTF-8 and UTF-16 encoding
- Provides both mutable and immutable APIs
Cons
- Limited to C and C++ languages
- May require manual memory management in some cases
- Less feature-rich compared to some larger JSON libraries
- Relatively new project, potentially less battle-tested than more established alternatives
Code Examples
- Parsing JSON:
const char *json = "{\"name\":\"John\",\"age\":30}";
yyjson_doc *doc = yyjson_read(json, strlen(json), 0);
yyjson_val *root = yyjson_doc_get_root(doc);
const char *name = yyjson_get_str(yyjson_obj_get(root, "name"));
int age = yyjson_get_int(yyjson_obj_get(root, "age"));
printf("Name: %s, Age: %d\n", name, age);
yyjson_doc_free(doc);
- Creating and serializing JSON:
yyjson_mut_doc *doc = yyjson_mut_doc_new(NULL);
yyjson_mut_val *root = yyjson_mut_obj(doc);
yyjson_mut_doc_set_root(doc, root);
yyjson_mut_obj_add_str(doc, root, "name", "Alice");
yyjson_mut_obj_add_int(doc, root, "age", 25);
char *json = yyjson_mut_write(doc, 0, NULL);
printf("%s\n", json);
free(json);
yyjson_mut_doc_free(doc);
- Working with arrays:
const char *json = "[1,2,3,4,5]";
yyjson_doc *doc = yyjson_read(json, strlen(json), 0);
yyjson_val *arr = yyjson_doc_get_root(doc);
size_t idx, max;
yyjson_val *val;
yyjson_arr_foreach(arr, idx, max, val) {
printf("%d ", yyjson_get_int(val));
}
yyjson_doc_free(doc);
Getting Started
To use yyjson in your project:
- Download the
yyjson.h
andyyjson.c
files from the GitHub repository. - Include them in your project:
#include "yyjson.h"
- Compile your project with the
yyjson.c
file:
gcc your_file.c yyjson.c -o your_program
- Start using yyjson functions in your code as shown in the examples above.
Competitor Comparisons
Parsing gigabytes of JSON per second : used by Facebook/Meta Velox, the Node.js runtime, ClickHouse, WatermelonDB, Apache Doris, Milvus, StarRocks
Pros of simdjson
- Utilizes SIMD instructions for faster parsing
- Supports in-situ parsing, reducing memory usage
- Offers both DOM and streaming APIs for flexibility
Cons of simdjson
- Limited to parsing only, no JSON generation capabilities
- Requires CPU support for specific SIMD instructions
- Larger codebase and more complex implementation
Code Comparison
simdjson:
simdjson::dom::parser parser;
simdjson::dom::element doc = parser.parse(json_string);
std::string_view result = doc["key"];
yyjson:
yyjson_doc *doc = yyjson_read(json_string, strlen(json_string), 0);
yyjson_val *val = yyjson_obj_get(yyjson_doc_get_root(doc), "key");
const char *result = yyjson_get_str(val);
Key Differences
- simdjson focuses on high-performance parsing using SIMD instructions
- yyjson offers a more comprehensive JSON handling solution, including both parsing and generation
- simdjson provides C++ APIs, while yyjson is primarily C-based
- yyjson has a smaller codebase and simpler implementation
- simdjson may have better performance for large JSON documents on supported hardware
Both libraries are well-maintained and offer efficient JSON parsing capabilities, but they cater to different use cases and programming environments.
A fast JSON parser/generator for C++ with both SAX/DOM style API
Pros of rapidjson
- More mature and widely adopted in production environments
- Supports both DOM and SAX parsing styles
- Extensive documentation and community support
Cons of rapidjson
- Larger codebase and memory footprint
- Slower parsing and serialization speed compared to yyjson
- More complex API, potentially steeper learning curve
Code Comparison
yyjson:
yyjson_doc *doc = yyjson_read(json, len, 0);
yyjson_val *root = yyjson_doc_get_root(doc);
const char *name = yyjson_get_str(yyjson_obj_get(root, "name"));
yyjson_doc_free(doc);
rapidjson:
Document d;
d.Parse(json);
const char* name = d["name"].GetString();
Key Differences
- yyjson is written in C, while rapidjson is in C++
- yyjson focuses on simplicity and performance, while rapidjson offers more features
- yyjson has a smaller codebase and is easier to integrate into projects
- rapidjson provides more flexibility with its DOM and SAX parsing options
Both libraries are high-performance JSON parsers, but they cater to different use cases. yyjson excels in scenarios where speed and simplicity are paramount, while rapidjson is better suited for complex applications requiring advanced JSON manipulation features.
JSON for Modern C++
Pros of json
- Widely adopted and well-established in the C++ community
- Extensive documentation and examples available
- Supports both SAX and DOM parsing styles
Cons of json
- Slower performance compared to yyjson, especially for large JSON files
- Higher memory usage due to its design and implementation
- More complex API, which may require a steeper learning curve
Code Comparison
yyjson:
yyjson_doc *doc = yyjson_read(json_str, strlen(json_str), 0);
yyjson_val *root = yyjson_doc_get_root(doc);
const char *name = yyjson_get_str(yyjson_obj_get(root, "name"));
yyjson_doc_free(doc);
json:
auto j = json::parse(json_str);
std::string name = j["name"];
While json provides a more concise API for simple operations, yyjson offers finer control over memory allocation and parsing options. yyjson's C API may be more verbose but allows for better performance optimization in certain scenarios.
Both libraries support serialization and deserialization of JSON data, but yyjson focuses on high performance and low memory usage, making it particularly suitable for applications dealing with large JSON files or requiring minimal resource consumption.
C/C++ JSON parser/generator benchmark
Pros of nativejson-benchmark
- Comprehensive benchmarking of multiple JSON libraries
- Provides detailed performance metrics for parsing and serialization
- Includes a wide range of test cases and data sets
Cons of nativejson-benchmark
- Primarily focused on benchmarking, not a standalone JSON library
- May not reflect real-world usage scenarios for all applications
- Requires more setup and configuration to use in projects
Code Comparison
nativejson-benchmark (benchmarking setup):
void BM_RapidJsonInsitu(benchmark::State& state) {
for (auto _ : state)
ParseInsitu<rapidjson::Document>(json);
}
BENCHMARK(BM_RapidJsonInsitu);
yyjson (parsing example):
yyjson_doc *doc = yyjson_read(json, len, 0);
yyjson_val *root = yyjson_doc_get_root(doc);
// Use the parsed JSON
yyjson_doc_free(doc);
Summary
nativejson-benchmark is a tool for comparing JSON library performance, while yyjson is a high-performance JSON library. nativejson-benchmark offers comprehensive benchmarking across multiple libraries, but requires more setup. yyjson provides a simple API for JSON parsing and serialization, focusing on performance and ease of use in applications.
Jsmn is a world fastest JSON parser/tokenizer. This is the official repo replacing the old one at Bitbucket
Pros of jsmn
- Extremely lightweight and simple to use
- No dynamic memory allocation, suitable for embedded systems
- Single-file implementation, easy to integrate
Cons of jsmn
- Limited functionality compared to yyjson
- Requires manual parsing of JSON values
- No built-in support for JSON creation or modification
Code Comparison
jsmn:
jsmn_parser p;
jsmntok_t t[128];
jsmn_init(&p);
int r = jsmn_parse(&p, json_string, strlen(json_string), t, sizeof(t)/sizeof(t[0]));
yyjson:
yyjson_doc *doc = yyjson_read(json_string, strlen(json_string), 0);
yyjson_val *root = yyjson_doc_get_root(doc);
Summary
jsmn is a minimalist JSON parser focused on simplicity and low memory footprint, making it ideal for embedded systems. However, it lacks advanced features and requires more manual work for parsing and handling JSON data.
yyjson, on the other hand, offers a more comprehensive JSON manipulation library with better performance and easier-to-use APIs. It provides additional functionality like JSON creation and modification, making it more suitable for complex JSON processing tasks in larger applications.
The choice between the two depends on the specific requirements of the project, such as memory constraints, performance needs, and the complexity of JSON operations required.
Convert designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual CopilotREADME
Introduction
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
, anddouble
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 onec
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);
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.
Write JSON string
// 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);
Read JSON file with options
// 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);
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);
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);
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
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
- Add documentation page.
- Add GitHub workflow for CI and codecov.
- Add more tests: valgrind, sanitizer, fuzzing.
- Support JSON Pointer to query and modify JSON.
- Add
RAW
type for JSON reader and writer. - 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.
Top Related Projects
Parsing gigabytes of JSON per second : used by Facebook/Meta Velox, the Node.js runtime, ClickHouse, WatermelonDB, Apache Doris, Milvus, StarRocks
A fast JSON parser/generator for C++ with both SAX/DOM style API
JSON for Modern C++
C/C++ JSON parser/generator benchmark
Jsmn is a world fastest JSON parser/tokenizer. This is the official repo replacing the old one at Bitbucket
Convert designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual Copilot