yyjson.h
Overview
`yyjson.h` is the primary public header for **yyjson**, an ultra-fast, memory-efficient, and fully compliant JSON parsing and writing C library. It provides APIs to read (parse), write (serialize), manipulate, and query JSON data structures. `yyjson` supports both immutable and mutable JSON documents, advanced JSON Pointer (RFC 6901), JSON Patch (RFC 6902), and JSON Merge Patch (RFC 7386) operations, along with customizable memory allocators.
The library is designed for high performance and low memory overhead, using optimized parsing algorithms (including a finite state machine with `goto`), efficient memory pools, and fast floating-point conversion. It also supports optional non-standard JSON features such as comments, trailing commas, and special floating-point literals.
Key Features
JSON Reader: Parse JSON strings, files, or file pointers into immutable documents.
JSON Writer: Serialize immutable or mutable JSON documents or values to strings or files.
Mutable Document API: Create and modify JSON documents and values dynamically.
JSON Pointers: Access and manipulate JSON values by RFC 6901 JSON Pointer syntax.
JSON Patch & Merge Patch: Apply RFC 6902 and RFC 7386 patches for JSON document transformations.
Custom Allocators: Use default, pool, or dynamic allocators for flexible memory management.
Compile-time Options: Enable/disable features like reader, writer, utilities, fast float conversion, non-standard JSON support, UTF-8 validation, and unaligned memory access.
Thread Safety: Thread-safe when using thread-safe allocators and ensuring input data is not modified concurrently.
Main Data Structures
JSON Documents and Values
Struct | Description | Mutable? | Usage |
|---|---|---|---|
`yyjson_doc` | Immutable JSON document for reading JSON | No | Holds all JSON values and strings for a parsed document |
`yyjson_val` | Immutable JSON value | No | Represents a JSON value inside an immutable document |
`yyjson_mut_doc` | Mutable JSON document for building JSON | Yes | Used to create or mutate JSON documents dynamically |
`yyjson_mut_val` | Mutable JSON value | Yes | Represents a JSON value inside a mutable document |
Memory Allocators
Struct | Description |
|---|---|
`yyjson_alc` | Custom memory allocator interface (malloc, realloc, free) |
Supports:
Pool Allocator: Pre-allocated fixed buffer for one JSON document.
Dynamic Allocator: Dynamically requests memory chunks and frees all at once.
Detailed API Descriptions
1. JSON Reader API
Purpose: Parse JSON data into immutable documents.
yyjson_read_opts
yyjson_doc *yyjson_read_opts(char *dat,
size_t len,
const yyjson_alc *alc,
yyjson_read_err *err);
Parameters:
dat: Pointer to JSON UTF-8 data (null-terminator not required).len: Length of JSON data in bytes.alc: Custom allocator;NULLuses libc default.err: Pointer to store error info; can beNULL.
Returns: Pointer to new
yyjson_docon success;NULLon failure.Usage:
yyjson_read_err err; yyjson_doc *doc = yyjson_read_opts(json_data, json_len, NULL, &err); if (!doc) { printf("Error: %s\n", err.msg); } else { // Use doc yyjson_doc_free(doc); }Notes: Supports various options via flags (e.g., in-situ parsing, comments allowed).
yyjson_read_file
Reads JSON from a file path with options and allocator.
2. JSON Writer API
Purpose: Serialize JSON documents or values to strings or files.
yyjson_write_opts
char *yyjson_write_opts(const yyjson_doc *doc,
yyjson_write_flag flg,
const yyjson_alc *alc,
size_t *len,
yyjson_write_err *err);
Parameters:
doc: JSON document to serialize.flg: Write options (pretty-print, escape unicode, allow inf/nan, etc.).alc: Allocator for output buffer (NULL= libc default).len: Output length (excluding null-terminator).err: Error info pointer.
Returns: JSON string buffer (UTF-8, null-terminated) on success;
NULLon failure.Usage:
size_t out_len; char *json_str = yyjson_write_opts(doc, YYJSON_WRITE_PRETTY, NULL, &out_len, NULL); if (json_str) { printf("%s\n", json_str); free(json_str); }
3. Mutable JSON API
Allows creation and modification of JSON documents and values.
Creating a mutable document
yyjson_mut_doc *mut_doc = yyjson_mut_doc_new(NULL); // NULL uses default allocator
Creating values
yyjson_mut_val *val = yyjson_mut_int(mut_doc, 42);
yyjson_mut_val *arr = yyjson_mut_arr(mut_doc);
yyjson_mut_val *obj = yyjson_mut_obj(mut_doc);
Adding values to arrays and objects
yyjson_mut_arr_add_int(mut_doc, arr, 7);
yyjson_mut_obj_add_str(mut_doc, obj, "key", "value");
Writing mutable documents
Use `yyjson_mut_write_opts()` to serialize.
4. JSON Pointer API (RFC 6901)
Provides functions to get, add, set, replace, and remove JSON values using JSON Pointer strings.
Example: Get a value by pointer.
yyjson_val *val = yyjson_doc_ptr_get(doc, "/foo/bar");
Mutate value by pointer:
yyjson_mut_val *mut_val = yyjson_mut_doc_ptr_get(mut_doc, "/foo/bar");
yyjson_mut_set_int(mut_val, 123);
Add new value by pointer (creates parents if needed):
yyjson_mut_doc_ptr_add(mut_doc, "/foo/baz", yyjson_mut_str(mut_doc, "new"));
5. JSON Patch API (RFC 6902) and Merge Patch API (RFC 7386)
Apply JSON patches or merge patches to mutable documents for advanced modifications.
yyjson_mut_val *patched = yyjson_mut_patch(mut_doc, orig_val, patch_val, &err);
Important Implementation Details
Finite State Machine (FSM) Parsing: Parsing is implemented using explicit
gotolabels for different JSON token states, minimizing overhead.Memory Pools: Mutable documents use linked lists of memory chunks for string and value pools to optimize allocations.
Tagged Union Values: JSON values use a 16-byte structure with a 64-bit tag encoding type, subtype, and length, and a union holding payload (number, string pointer, or pointer to children).
Circular Linked Lists: Mutable arrays and objects use circular linked lists for elements, allowing O(1) append/prepend operations.
Fast Floating-Point Conversion: Uses optimized algorithms with fallback to bigint parsing for precise IEEE-754 compliance.
UTF-8 Validation: Optional compile-time and run-time UTF-8 validation for security and compliance.
Non-Standard JSON Features: Can be enabled/disabled for comments, trailing commas, inf/nan literals, invalid Unicode, etc.
Custom Allocators: Abstract allocator interface to plug in different memory management strategies.
Interaction with Other System Components
The
yyjsonlibrary serves as the embedded JSON engine for higher-level Rust and Python modules.Rust code conditionally compiles to use
yyjsonC parsing for deserialization when theyyjsonfeature is enabled.Python bindings call into this library for fast JSON parsing and writing.
Benchmarking modules measure
yyjsonperformance versus other JSON libraries.Custom allocators and memory pool management interface cleanly with Rust's ownership and Python's memory management through FFI.
Example Usage
Parsing JSON string
const char *json = "{\"name\":\"John\",\"age\":30,\"isStudent\":false}";
yyjson_doc *doc = yyjson_read(json, strlen(json), 0);
if (doc) {
yyjson_val *root = yyjson_doc_get_root(doc);
yyjson_val *name = yyjson_obj_get(root, "name");
printf("Name: %s\n", yyjson_get_str(name));
yyjson_doc_free(doc);
}
Creating and serializing a mutable JSON
yyjson_mut_doc *doc = yyjson_mut_doc_new(NULL);
yyjson_mut_val *obj = yyjson_mut_obj(doc);
yyjson_mut_doc_set_root(doc, obj);
yyjson_mut_obj_add_str(doc, obj, "city", "New York");
yyjson_mut_obj_add_int(doc, obj, "year", 2024);
size_t len;
char *json_str = yyjson_mut_write(doc, YYJSON_WRITE_PRETTY, &len);
if (json_str) {
printf("%s\n", json_str);
free(json_str);
}
yyjson_mut_doc_free(doc);
Visual Diagram: yyjson.h API Structure
flowchart TD
A[yyjson.h API]
A --> B[JSON Reader]
A --> C[JSON Writer]
A --> D[Mutable JSON API]
A --> E[JSON Pointer API]
A --> F[JSON Patch & Merge Patch API]
A --> G[Memory Allocators]
B --> B1[yyjson_read_opts()]
B --> B2[yyjson_read_file()]
B --> B3[yyjson_doc_free()]
C --> C1[yyjson_write_opts()]
C --> C2[yyjson_write_file()]
D --> D1[yyjson_mut_doc_new()]
D --> D2[yyjson_mut_val creation functions]
D --> D3[yyjson_mut_arr_add_*()]
D --> D4[yyjson_mut_obj_add_*()]
D --> D5[yyjson_mut_doc_free()]
E --> E1[yyjson_doc_ptr_get()]
E --> E2[yyjson_mut_doc_ptr_set()]
E --> E3[yyjson_mut_doc_ptr_add()]
E --> E4[yyjson_mut_doc_ptr_remove()]
F --> F1[yyjson_patch()]
F --> F2[yyjson_merge_patch()]
G --> G1[yyjson_alc struct]
G --> G2[Pool allocator: yyjson_alc_pool_init()]
G --> G3[Dynamic allocator: yyjson_alc_dyn_new()]
Summary
`yyjson.h` is a comprehensive, high-performance C library interface for JSON manipulation. It provides a rich set of APIs for reading, writing, creating, editing, and patching JSON data, supporting both immutable and mutable models, advanced JSON Pointer operations, and customizable memory allocation strategies. The library is optimized for speed and low memory overhead, suitable for integration in systems requiring efficient JSON processing such as embedded applications, Rust and Python bindings, and high-throughput backend services.