reliakit-json
A strict, bounded, and deterministic JSON library for Rust.
reliakit-json is built for systems that process untrusted JSON or need
predictable output — API payloads, protocol messages, config, audit logs,
and signed or hashed documents. It parses a strict subset of RFC 8259, rejects
duplicate object keys, enforces explicit resource limits, preserves number
precision, reports errors with location and path, and serializes
deterministically. It has no external dependencies, forbids unsafe code, and
runs on no_std (with alloc).
Its scope is deliberately narrow: no derive macros, no schema validation, no JSON5, no comments, no trailing commas, no lenient parsing, no SIMD. The goal is predictable behavior on hostile input, not maximum throughput or convenience.
What it guarantees
- Strict parsing. A conservative, I-JSON-oriented subset of RFC 8259.
- Duplicate keys are rejected, not silently resolved — and detection happens
after escape decoding, so
"role"and"role"collide. - Explicit resource limits are part of the API. Untrusted parsing cannot run away on input size, nesting depth, string/number length, item counts, or total nodes.
- Numbers keep their exact text. No silent rounding; conversions to
i64/u64/f64are explicit and fallible.NaN/Infinityare never accepted. - Actionable errors with a stable kind, byte offset, line, column, and the
JSON path (
$.users[4].email) being processed. - Deterministic output. The compact writer preserves member order and exact number text; the same value always serializes to the same bytes.
no_std + alloc, zero dependencies,#![forbid(unsafe_code)].
Rejected by default
Invalid UTF-8, a leading byte-order mark, comments, trailing commas, trailing
data, unescaped control characters, invalid escapes, malformed \uXXXX,
unpaired UTF-16 surrogates, duplicate keys, NaN/Infinity, leading +,
leading zeros, malformed numbers, and anything exceeding the configured limits.
Installation
[]
= "0.1"
This crate is no_std-compatible (default-features = false); the default
std feature only adds std::error::Error implementations. It always requires
alloc.
Usage
use ;
let value = parse_str.unwrap;
let object = value.as_object.unwrap;
assert_eq!;
assert_eq!;
// Deterministic, member-order-preserving output.
assert_eq!;
Parse untrusted input under explicit limits:
use ;
let limits = conservative.with_max_depth;
match parse_with_limits
parse and parse_str apply JsonLimits::new (a conservative default)
automatically — there is no implicitly unlimited entry point.
API
| Item | Purpose |
|---|---|
parse(&[u8]) / parse_str(&str) |
Parse with default limits. |
parse_with_limits(&[u8], JsonLimits) |
Parse with an explicit limit profile. |
JsonValue |
Owned value: Null, Bool, Number, String, Array, Object. |
JsonNumber |
Precision-preserving number; to_i64 / to_u64 / to_f64 / try_from_f64. |
JsonObject |
Unique-key, insertion-ordered map (get, insert, iter). |
JsonLimits |
new / conservative / permissive profiles + with_* builders. |
JsonError / JsonErrorKind / JsonLimitKind / JsonPath |
Located, classified errors. |
to_compact_string / to_compact_vec |
Deterministic compact serialization. |
Numbers
JSON numbers are kept as their exact source text and never auto-converted to
f64. Equality is structural — 1.0, 1, and 1e0 are distinct values;
compare numerically by converting first. Conversions report whether they failed
on range, integer-ness, or finiteness.
Limits
JsonLimits bounds logical decoded data (counts and byte lengths), not exact
allocator memory. Profiles: conservative() (small, low-trust payloads),
new() (the default), and permissive() (larger trusted documents) — all
explicit and finite. Tune individual fields with the with_* builders.
When to use it
- Parsing untrusted JSON where predictable failure matters more than speed.
- Producing stable, deterministic JSON for hashing, signing, or content addressing.
- Embedded or
no_stdservices that still need a careful JSON reader/writer.
When not to use it
- You want automatic struct (de)serialization driven by derive macros.
- You need the fastest possible parsing throughput above all else.
- You need JSON5, comments, or lenient parsing — this crate rejects them by design.
Roadmap
RFC 8785 (JSON Canonicalization Scheme) output is planned, but will only be exposed once it passes the reference vectors, idempotence, differential, and fuzzing gates. It is not part of this release.
Safety
#![forbid(unsafe_code)]. Parsing uses depth-bounded descent and saturating
arithmetic; there is no known input that causes a panic or unbounded work.
Minimum Supported Rust Version
Rust 1.85 and newer. No nightly features are used.
License
Licensed under the MIT License. See LICENSE.