JSON to Rust
Generate Rust structs from a JSON sample, ready for serde_json. Field names are converted to snake_case with a #[serde(rename)] attribute where the JSON key differs, and anything optional or nullable is wrapped in Option<T>.
How to generate Rust structs from JSON
- Paste a JSON sample — ideally an array of several records, so optional fields are detected.
- Set the Root type name. Nested objects are named after the key that holds them, singularised for arrays.
- Adjust the Derive list if you need
PartialEq,Default, or fewer traits. - Tick skip_serializing_if so
Nonefields are omitted when serialising rather than written asnull. - Copy the code, or download it as a file.
Type mapping
- Integers →
i64. Change tou32,i32oru64where you know the range — the sample cannot tell you. - Fractional numbers →
f64. - Strings →
String. Switch to&'a strorCow<str>if you are optimising allocations. - Arrays →
Vec<T>. - Objects → a named struct.
- null / mixed types →
serde_json::Value, which accepts anything.
Getting good types out of a sample
Type inference from a sample is only as good as the sample. Three habits make the output far more useful:
- Paste an array, not one record. When you pass several records, a key missing from any of them is marked optional and a field that is sometimes a number and sometimes a float widens to a float. One record makes everything look required.
- Include the awkward cases. A record with a null, an empty array, and a missing optional key teaches the generator more than ten identical happy-path records.
- Check unions by hand. A field that holds different shapes in different records falls back to the language's "any" type. That is a signal your data has a variant the generator cannot express — model it explicitly.
Privacy
Nothing is uploaded. Inference and code generation run in this tab. No server sees the payload you paste — which matters, because real API responses tend to contain real user data.
FAQ
Why is a field Option even though it is always present?
Because it held null in at least one record. In serde, null and "key absent" are different things: Option<T> covers both, so it is the safe choice.
Do I need serde_json in Cargo.toml?
You need serde with the derive feature always, and serde_json if the output mentions serde_json::Value or you are parsing JSON: serde = { version = "1", features = ["derive"] }.
Can it generate enums for variant shapes?
No. Tagged enums require knowing which field is the discriminator, which a sample does not reveal. Mixed shapes become serde_json::Value — replace that with a hand-written enum and #[serde(tag = "…")].