Nihilai Collective Logo

Jsonifier

Nihilai Collective

RFC8259-compliant JSON · SIMD + compile-time hash-maps · C++20

What It Is

Jsonifier is a set of classes for validating, serializing, parsing, prettifying, and minifying objects into and out of JSON strings — very rapidly. It is fully RFC8259 compliant, and is positioned as possibly the fastest JSON parser and serializer in C++.

It achieves this through the combined use of SIMD instructions and compile-time hash-maps for the keys of the data being parsed — so key lookup stays O(1) and order-independent rather than degrading on out-of-sequence documents. Registered on the Microsoft vcpkg registry.

Why

Most fast JSON libraries are fast on the happy path and fragile everywhere else. Jsonifier is built to be fast and unbreakable. The serializer leans on compile-time reflection over your types, the parser resolves keys through a perfect hash computed at compile time, and the SIMD layer dispatches to the widest instruction set your CPU supports.

Jsonifier doesn't just parse JSON — it survives it. Every build is hardened against malformed input by a fuzz-simulation test that corrupts a 2000-plus-character JSON string one byte at a time, generating thousands of progressively invalid permutations and force-feeding each through both parsing and schema validation. Zero crashes, zero memory violations, zero undefined behavior — under both AddressSanitizer and UndefinedBehaviorSanitizer, across the full Windows / Linux / macOS matrix, on every push.

Features

  • Fully RFC8259-compliant parsing and serialization
  • Parse, serialize, validate, prettify, and minify — one library
  • SIMD dispatch across AVX-512 / AVX2 / AVX / SSE / NEON
  • Auto-detected CPU arch — x64, AVX, AVX2, AVX-512, ARM-NEON
  • Manual override via JSONIFIER_CPU_FLAGS in CMake
  • Compile-time perfect hash-maps for key resolution
  • Specialized hash maps for 1-, 2-, 3+-field objects
  • Order-independent parsing — no penalty for out-of-sequence keys
  • Partial reading: extract only the keys you ask for
  • Compile-time reflection — no macros, no schema boilerplate
  • Zero-copy parsing where possible
  • ASAN / UBSAN clean against a byte-level fuzz gauntlet
  • Custom parsing/serializing behavior per type
  • Parse arbitrary / unknown data via raw_json_data
  • Runtime key exclusion
  • Detailed error reporting with source-location tracking
  • Optimization mode for already-minified JSON
  • Cross-platform CI: Windows MSVC, Ubuntu GCC/Clang, macOS Clang/GCC

Quick Start

Define a type and parse into it
#include <jsonifier/Index.hpp> struct Person { std::string name; int32_t age; double height; bool active; }; template<> struct jsonifier::core<Person> { using value_type = Person; static constexpr auto parseValue = createValue< &value_type::name, &value_type::age, &value_type::height, &value_type::active>(); }; int main() { jsonifier::jsonifier_core<> parser{}; std::string json = R"({"name":"John","age":30,"height":1.85,"active":true})"; Person person{}; parser.parseJson(person, json); }
Serialize back out
std::string out{}; parser.serializeJson(person, out); // out == {"name":"John","age":30,"height":1.85,"active":true}
Validate, prettify, minify
bool ok = parser.validateJson(json); std::string pretty = parser.prettifyJson(json); std::string minified = parser.minifyJson(pretty);

Every error surfaces through the parser's error vector — see the Error Handling docs for the full reporting API.

Building

Consume via CMake's FetchContent, or install through vcpkg.

vcpkg

vcpkg install jsonifier

CMake (FetchContent)

include(FetchContent) FetchContent_Declare( Jsonifier GIT_REPOSITORY https://github.com/RealTimeChris/Jsonifier.git GIT_TAG main ) FetchContent_MakeAvailable(Jsonifier) target_link_libraries(your_target PRIVATE Jsonifier::Jsonifier)

Requirements

  • A C++20 compiler — MSVC 2022+, GCC 11+, Clang 14+
  • CMake 3.18 or later
  • Supported CPU — x64 or ARM64 with NEON

Testing & Safety

Every push triggers the full test suite across Windows MSVC, Ubuntu GCC, Ubuntu Clang, macOS Clang, and macOS GCC — with both AddressSanitizer and UndefinedBehaviorSanitizer live, treating warnings as errors under -Weverything / -Wpedantic / /Wall /W4.

Every parsing-family test runs in all eight partialRead × knownOrder × nullTerminated configurations, so every code path — full-document, partial, ordered, out-of-order, and null-terminated vs. length-delimited — gets the same coverage.

RFC8259 Conformance
266 fail-case + 117 pass-case documents (77+27 from the jsonchecker corpus, plus 189+90 from JSONTestSuite), each run in all eight partial × knownOrder × nullTerminated configurations — 3,064 assertions per platform.
Bounds & Truncation Fuzz
17 corpus files, minified and prettified (34 total), each sliced byte-by-byte down to empty. Every truncation must fail parse cleanly. Run across all eight configs — 272 truncation runs.
Float Validation
64 edge cases: denormals, infinities, subnormal boundaries, extreme magnitudes, powers-of-two rounding cases, 46-digit mantissas. Run in all eight configurations.
Integer Bounds
Signed: 24 pass + 11 fail, covering INT64_MIN / INT64_MAX overflow. Unsigned: 16 pass + 11 fail through UINT64_MAX. All run in every configuration.
String & Unicode
35 pass + 26 fail cases: escape sequences, control characters, surrogate pairs, emoji, ZWJ sequences, unpaired surrogates, overlong escapes, truncated hex.
UTF-8 Validation
Expanded well past standalone byte-sequence checks: the full Markus Kuhn UTF-8 stress-test corpus, second-byte boundary tests per lead-byte class, fused string-parser validation (escape-aware, cross-chunk, surrogate-pair-aware), an unaligned-pointer sweep, an unaligned invalid-sequence sweep, an mmap page-boundary fault check, and a width-transition sweep across body lengths 24–224.
Round-Trip
27 serialize → parse → compare tests covering pointers, unique_ptr, nulls, empties, large numbers, exponent forms. Run in all eight configurations.
Reflection & Type Coverage
70+ unit tests: basic reflection, renamed fields, optionals, enums as integers and map keys, tuples, shared_ptr, nested maps, vector-of-vectors, escaped keys, plus a dedicated partial-read suite (boundary lengths, large payloads, minified mode).
Parsing Corpus
Full benchmark corpus (Twitter, CitmCatalog, Canada, Marine IK, Discord, Github Events, etc.) parsed and re-serialized in every configuration, plus minify / prettify / validate passes.
Sanitizer Coverage
ASAN with use-after-scope, sibling-call disabling, and _FORTIFY_SOURCE off. UBSAN with -fno-sanitize-recover=all so any UB fails the run. Static-linked libasan on Linux CI.
Warnings-as-Errors
Clang builds under -Weverything -Wpedantic -Werror. GCC under -Wpedantic -Wextra -Wall -Werror. MSVC under /Wall /W4 /WX. Zero warnings tolerated.
Total Assertions
Well over 4,000 individual assertions per platform per push, across five platform / compiler combinations, every one under both sanitizers.
Run the test suite locally
git clone https://github.com/RealTimeChris/Jsonifier.git cd Jsonifier cmake -B build -DJSONIFIER_UNIT_TESTS=ON cmake --build build --target jsonifier-unit-tests ./build/Tests/jsonifier-unit-tests

Add -DJSONIFIER_ASAN=ON or -DJSONIFIER_UBSAN=ON to enable sanitizers locally. Both are on by default in CI.

Documentation

InstallationFetchContent and vcpkg setup
ReflectionDescribing your types to the core template
Serializing / ParsingThe primary read and write APIs
Partial ReadingExtract only the fields you need
ValidatingRFC8259 conformance checking
Prettifying / MinifyingWhitespace-aware reformatting
Optimizing for Minified JSONPerformance mode for already-minified input
Error HandlingInspecting parse and validation failures
CPU Architecture SelectionControlling SIMD dispatch
Excluding Keys at RuntimeSkipping fields dynamically
Custom Parsing / SerializingPer-type behavior overrides
Parsing Arbitrary Dataraw_json_data for unknown shapes
Full usage guide on GitHub →

Benchmark Methodology

Throughput is measured in megabytes processed per second (MB/s) for both reading (parse) and writing (serialize), benchmarked against Glaze and simdjson on identical hardware.

The harness uses adaptive epoch sampling — the exact iteration counts, convergence thresholds, and timing bounds for each run are read live from that run's own results CSV (below the platform/compiler tabs) rather than restated here, since they can vary per run. In general, each epoch evaluates a trailing window of samples and requires the relative standard error and the epoch-over-epoch mean shift to both fall under their configured thresholds simultaneously — the first epoch satisfying both conditions is retained as the canonical result.

If convergence is never reached before the configured time limit elapses or the iteration cap is hit, the result is marked non-converged and excluded from all rankings — only converged results participate in win/tie/loss tallying. Statistical ties are detected via Welch's t-test on Bessel-corrected variance , so a small delta inside the noise floor doesn't get dressed up as a victory.

The output of each call is consumed through do_not_optimize_away() so the compiler can't eliminate the work, and input data is regenerated per iteration to prevent branch predictors and data caches from learning the input distribution.

Platforms: Windows, Linux, macOS — Compilers: MSVC, GCC, Clang — Harness: BenchmarkSuite

View the full benchmark repository →

Results

Benchmark Branch
Platform / Compiler
Loading benchmarks
Operation

Correctness Validation

Structural parity with simdjson, verified byte-for-byte across the entire benchmark corpus. Each test document is parsed by both libraries; every emitted structural token is compared. A single mismatch fails the run.

Results are pulled from the server's correctness-validation data set, matching the currently selected benchmark branch above.

Platform / Compiler
Loading correctness data

Engineering Papers

Deep-dive writeups on Jsonifier's architecture, written for readers who want the actual mechanism rather than the marketing summary.

Two Stages, On Demand: The Stage-1 + Stage-2 Architecture in Jsonifier

Nihilai Collective Corp — Engineering Papers · Chris M. (RealTimeChris) · July 2026 · Jsonifier

Why Jsonifier treats the classic two-stage SIMD parsing model as a specialized tool rather than a mandatory front door — routing full-document parses through a single fused pass while reserving stage-1 structural indexing for partial reads, prettifying, and minifying. Covers the per-compiler step geometry, the fold-expression drain architecture for bitmask-to-index extraction, and the distributed in-register UTF-8 validation strategy, with direct comparisons to simdjson's current design throughout.

Read the full paper →

Batched Drain, Fused Scan: The Architecture of Jsonifier's Stage 1

Nihilai Collective Corp — Engineering Papers · Chris M. (RealTimeChris) · July 2026 · Jsonifier

A point-by-point comparison of Jsonifier's stage-1 structural indexer against simdjson's: a batched drain that decouples mask production from tape emission, per-(ISA × compiler)-tuned step geometry, an AVX-512 compress-based extraction path, and UTF-8 validation fused directly into string unescaping and carried across SIMD width transitions via a compact three-byte validation state. Includes a case study on relocating control-character validation from stage 1 to stage 2, plus full cross-platform results — 134 wins, 7 ties, 19 losses against simdjson across 160 tests, with perfect 32-0-0 sweeps on two of five platform/compiler targets.

Read the full paper →

Acknowledgments

Jsonifier stands on the shoulders of prior work in the high-performance JSON and numeric-conversion space. Credit where it's owed: