JSON to Rust Converter
Generate Rust structs with serde derives from a JSON sample — Option<T> for nullables, Vec<T> for arrays, rename attributes for wire names.
Serde structs from a sample
In Rust, JSON handling starts with a struct and #[derive(Serialize, Deserialize)] — and for a realistic API response, writing that struct tree by hand means a lot of careful Option and Vec decisions. The generator makes them from evidence: null in the sample → Option<T>, arrays → Vec<T>, each object shape → its own struct, wire names preserved via #[serde(rename = "…")] where they don't match Rust's snake_case.
Types you can trust the compiler with
Rust's payoff is that the compiler enforces what the struct claims — which cuts both ways: an over-narrow type from a thin sample means serde_json::from_str errors at runtime on real data. Feed a representative sample (several array entries, the null cases you actually see) and the generated i64/f64/Option decisions will hold up. Integers default to i64, decimals to f64 — narrow deliberately, not optimistically.
Drop-in usage
Add serde (with the derive feature) and serde_json to Cargo.toml — the JSON to TOML converter is right there if you're assembling the config — paste the structs, and let data: Root = serde_json::from_str(&body)?; completes the pipeline.
Frequently asked questions
Which serde attributes does the output use?
derive(Serialize, Deserialize) on every struct, plus serde(rename = "...") wherever the JSON key differs from the snake_case Rust field. No custom deserializers — plain declarative serde.
Why Option<T> on some fields?
Because the sample showed null (or the field missing in some array entries). Option is the honest type: unwrap consciously or pattern-match, instead of crashing on the first real-world payload.
Why i64 and f64 instead of smaller types?
JSON numbers are width-less, so the generator picks the types that cannot overflow on plausible data. Narrowing to u32/i32/f32 is your call where the domain guarantees it — the compiler will hold you to it.
What crates do I need?
serde = { version = "1", features = ["derive"] } and serde_json = "1". Nothing else — the generated code is dependency-minimal by design.