json-bourne 0.1.1

Type-driven JSON parser. no_std-first. Zero-dep.
Documentation

Type-driven JSON: parse straight into the caller's chosen type and serialize from it, with no generic Value middle layer.

json-bourne skips the dynamic-tree intermediate that crates like serde_json use. Each type knows how to deserialize itself from a [Lexer] (via FromJson) or write itself to a [JsonWrite] sink (via [ToJson]). The typed structure already enforces JSON's grammar, so the per-event state machine is pure overhead for typed consumers — skipping it makes the typed path ~2× faster on integer / string-heavy payloads.

  • No proc-macros. [from_json!], [to_json!], and [json!] are declarative macro_rules!. Empty dependency graph.
  • no_std everywhere. The streaming [Lexer] / [Parser] layer is no_std always; with the default std feature off the crate is no_std + alloc, and with alloc off too it is pure no_std.
  • Borrowed strings by default. &'input str and Cow<'input, str> parse zero-copy when the input contains no escapes.
  • Bounded by construction. Container nesting is depth-limited (default 128, const-generic). The streaming parser is a state machine with no recursion.

Quick start

Parse a primitive directly into a Rust type:

use json_bourne::parse_str;
let n: u32 = parse_str("42").unwrap();
assert_eq!(n, 42);

Parse a struct (no proc-macro — from_json! is declarative):

use json_bourne::{from_json, parse_str};

from_json! {
    #[derive(Debug, PartialEq)]
    struct User<'input> {
        id: u64,
        name: &'input str,
        active: bool,
    }
}

let u: User<'_> = parse_str(r#"{"id":1,"name":"alice","active":true}"#).unwrap();
assert_eq!(u.name, "alice");

Serialize back out:

use json_bourne::{to_json, to_string};

to_json! {
    struct Point { x: i32, y: i32 }
}

let s = to_string(&Point { x: 3, y: -7 }).unwrap();
assert_eq!(s, r#"{"x":3,"y":-7}"#);

Output destinations

Sink Entry point
String [to_string]
Vec<u8> [to_vec]
String (pretty-printed) [to_string_pretty]
any [std::io::Write] [to_writer] (std only)
any [core::fmt::Write] [to_fmt]

Custom sinks implement [JsonWrite] directly.

Features

Feature Default Purpose
std yes HashMap, std::net, std::path, to_writer
alloc yes String, Vec, Box/Rc/Arc, escape decoding
indexmap no IndexMap / IndexSet (insertion order)

default-features = false plus ["alloc"] gives a no_std + alloc build. default-features = false alone gives pure no_std: only the streaming [Lexer] / [Parser] and typed APIs that don't need a heap (e.g. parsing into stack-allocated primitives) are available.