Convert JSON to Rust structs with serde Serialize and Deserialize
A free JSON to Rust converter: paste JSON and get serde structs back instantly. Each struct derives Serialize and Deserialize, field types are inferred from the data, nested objects become their own structs, and keys that can be null or missing become Option<T> so deserialization does not fail. #[serde(rename)] keeps the original JSON key names, and keywords such as type become raw identifiers. Conversion runs entirely in your browser, so your JSON is never uploaded to a server.
Output format: Struct — serde structs deriving Serialize and Deserialize.
| Option | What it does |
|---|---|
| Root Struct Name | Names the top-level Struct. |
| Field Naming Convention | One of snake_case, camelCase, PascalCase, Preserve Original. Defaults to snake_case. |
| Type for null values | Either serde_json::Value or String, used when a key is null in every sample. |
| Add #[serde(rename)] | Annotate every field whose name differs from its JSON key with #[serde(rename = "...")]. Without it a field only binds to a key spelled exactly like it, so a camelCase key read into a snake_case field fails as a missing field. |
| Skip None when serializing | Add skip_serializing_if = "Option::is_none" to every Option field so a null or missing value is left out of the serialized JSON instead of written as null. |
| JSON value | Rust type |
|---|---|
| string | String |
| integer | i32 |
| integer beyond 32 bits | i64 |
| decimal | f64 |
| true / false | bool |
| ISO-8601 timestamp with a zone | chrono::DateTime<Utc> |
| array | Vec<T> |
| object | nested struct |
| null or missing in some samples | Option<T> |
| null | serde_json::Value (configurable) |
{
"id": 12345,
"product_name": "Wireless Mouse",
"price": 24.99,
"in_stock": true,
"tags": ["electronics", "accessories"],
"manufacturer": {
"name": "Acme Corp",
"country": "US"
}
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Product {
pub id: i32,
pub product_name: String,
pub price: f64,
pub in_stock: bool,
pub tags: Vec<String>,
pub manufacturer: Manufacturer,
}
Paste your JSON into the input pane and the Rust structs appear beside it immediately. Set the root struct name, then copy the code or download it. Add serde and serde_json to Cargo.toml (the generated file lists the crates it needs in a comment) and call serde_json::from_str::<Root>(&json). Nested JSON objects become their own structs and arrays become Vec<T>.
serde treats a missing Option<T> as None, but a plain T fails with a "missing field" error when its key is absent or null. A field becomes Option<T> whenever the sample shows it null or missing in at least one object, so the struct deserializes every example you pasted.
They become raw identifiers (r#type), which serde reads back as the plain word, so no rename is needed. The four keywords that cannot be raw identifiers (self, Self, super, crate) get a trailing underscore plus an explicit #[serde(rename)].
chrono::DateTime<Utc> only parses RFC 3339 timestamps, which must carry a zone (Z or an offset). A timestamp without a zone would compile but fail at runtime, so it stays a String; a timestamp with a zone becomes DateTime<Utc>, and the generated header lists the chrono crate with its serde feature.
No. Parsing, type inference, and code generation all run in your browser using JavaScript. Your JSON is never sent to a remote server, and there is no account to create. The page keeps your last input and settings in your own browser (localStorage) so they survive a reload; nothing is stored anywhere else.
The conversion itself never transmits your JSON, so a confidential payload does not leave your machine. You can verify this: open your browser DevTools, switch to the Network tab, and convert something — no request carries your data. Two things to know: your last input is saved in your browser's localStorage (clear site data to remove it), and the Copy Link button embeds your JSON in the link, so anyone who opens that link, and the server that receives the request, can see it. Only share such links where you are comfortable with that.
No. The generator is free to use with no sign-up and no usage limits.
Each nested JSON object becomes its own named type, derived from the key it appeared under. Arrays of objects are widened across every element, so a field that is a whole number in one element and a fraction in another gets a type that holds both.