JSON to Rust
Generate Rust structs with serde derives from JSON: Option<T> for optional fields, rename_all for camelCase APIs, and raw identifiers for keywords like type.
Local workspace
Named projects in IndexedDB · Local only — never synced to our servers. Worksp…
Batch workspace
Format multiple files locally in one run.
Serde makes JSON in Rust fast and type-safe, but only as accurate as the structs you write. This generator merges every item of an array to find fields that can be missing or null and wraps them in Option<T>, widens numbers to f64 when any sample is fractional, and turns keys into snake_case fields. It uses one rename_all attribute for camelCase APIs instead of a rename on every field, and handles keywords like type with raw identifiers. Mixed types become serde_json::Value, and identical nested objects share one struct.
Common errors and fixes
missing field `email`
The key isn't in the data. Add a sample without it so the field becomes Option<T>, or annotate the field with #[serde(default)].
invalid type: string "42", expected i64
The payload sends a number as a string. Change the field to String, or deserialize it with a helper such as serde_with's DisplayFromStr.
invalid type: floating point `18.25`, expected i64
Real data has a fractional value the sample didn't. Include a fractional sample so the field is generated as f64.
invalid type: sequence, expected struct Root
The JSON root is an array. Deserialize into the generated Vec type, such as RootList, instead of Root.
Options
| Option | Description |
|---|---|
| Root name | Name of the top-level struct. Nested structs are named after their JSON keys. |
| Derive Debug and Clone | Adds Debug and Clone to the Serialize and Deserialize derives. |
FAQ
Which crates does the generated Rust code need?
serde with the derive feature, and serde_json to parse. In Cargo.toml: serde = { version = "1", features = ["derive"] } and serde_json = "1".
Why is a field Option<T>?
The key is missing from some samples or holds null. Serde deserializes a missing Option field as None, and skip_serializing_if keeps None out of the output when you serialize.
What does rename_all = "camelCase" do?
It maps every snake_case field name to a camelCase key for the whole struct, so userId becomes user_id without a rename on each field. The generator uses it only when every key in the struct follows camelCase, and falls back to per-field renames otherwise.
Why is a field named r#type?
type is a Rust keyword, and the r# prefix makes it usable as a field name while serde still reads the key "type". self, super, and crate can't be raw identifiers, so they get a trailing underscore and a rename.
When does the generator use serde_json::Value?
When the samples have different types at a key, such as a number and a string, or only null. You can inspect the Value at runtime or replace it with an untagged enum.