JSON to Rust Converter
Generate Rust structs from JSON. Paste your JSON:
Generate Rust Structs from JSON
This tool converts JSON to Rust structs with Serde derive macros for serialization and deserialization.
Example Output
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(rename_all = "camelCase")]
pub struct User {
pub id: i32,
pub user_name: String,
pub is_active: bool,
}Type Mapping
| JSON | Rust |
|---|---|
| string | String |
| integer | i32 / i64 |
| decimal | f64 |
| boolean | bool |
| null | Option<String> |
| array | Vec<T> |
| object | Nested struct |
Using Generated Code
// Add to Cargo.toml:
// serde = { version = "1.0", features = ["derive"] }
// serde_json = "1.0"
let json = r#"{"id": 1, "userName": "john"}"#;
let user: User = serde_json::from_str(json)?;
println!("{:?}", user);Related Tools
- JSON to Go — Generate Go structs
- JSON to TypeScript — For web apps
- JSON Validator — Validate JSON first
Common Mistakes & Pro Tips
- serde maps keys by exact name — use rename attributes — serde matches a struct field to the JSON key of the same name, so a camelCase key won't bind to a snake_case field. Add `#[serde(rename = "createdAt")]` per field, or apply `#[serde(rename_all = "camelCase")]` on the struct to convert idiomatic snake_case Rust fields to/from camelCase JSON automatically.
- Numbers become i64 or f64 — pick width deliberately — serde_json deserializes integers into whatever integer type your field declares; the generator typically picks `i64` for whole numbers and `f64` for decimals. Choose `u64` for non-negative IDs, `i32` when range allows, and remember `f64` can't exactly represent values like 0.1. JSON numbers larger than `i64`/`u64` need `serde_json::Number` or a bignum type.
- Option<T> for nullable, plus default for missing keys — A JSON `null` maps to `Option<T>` where `None` is null. But a *missing* key still causes a deserialize error unless you also add `#[serde(default)]`, which fills in `None`/`Default::default()` when the key is absent. Combine them (`#[serde(default)] field: Option<T>`) to tolerate both null and missing.
- Empty and mixed arrays don't yield a usable element type — An empty array `[]` gives no element type, so it falls back to `Vec<serde_json::Value>`; a heterogeneous array does the same or forces an enum. Replace `Value` with the concrete element type (e.g. `Vec<Item>`) once known, since `Value` defeats Rust's type safety and requires manual matching.
- Raw identifiers and dates need handling — JSON keys that are Rust keywords (`type`, `match`, `ref`) can't be plain field names; use a raw identifier (`r#type`) or rename the field and add `#[serde(rename = "type")]`. Date strings stay `String` unless you opt into `chrono`/`time` with a serde feature, since serde has no built-in date type.
Frequently Asked Questions
What derives do the generated structs include?
Typically `#[derive(Serialize, Deserialize)]` from serde, often alongside `Debug` and `Clone`. `Deserialize` is what lets `serde_json::from_str` build the struct; `Serialize` enables `to_string`. You'll need serde in Cargo.toml with the `derive` feature (`serde = { version = "1", features = ["derive"] }`) plus `serde_json`.
How do I handle optional or nullable fields?
Wrap the type in `Option<T>` so JSON `null` deserializes to `None`. To also allow the key to be entirely absent without an error, add `#[serde(default)]`, which supplies `None` for missing keys. For serializing, `#[serde(skip_serializing_if = "Option::is_none")]` omits null fields from the output.
Why does deserialization fail when a field is missing?
By default serde requires every non-`Option` field to be present and errors on a missing key. Add `#[serde(default)]` to the field (or `#[serde(default)]` on the struct) so missing keys fall back to `Default::default()`. Unknown extra keys are ignored by default unless you add `#[serde(deny_unknown_fields)]`.
Should integer fields be i32, i64, or u64?
Use `u64` for non-negative identifiers and counts, `i64` for general signed integers and timestamps, and `i32`/`u32` only when you're certain values fit. serde_json will error at runtime if a value overflows the chosen type, so widen when in doubt. There's no automatic widening — the field type you declare is enforced strictly.
How are nested objects and enums handled?
Each nested object becomes its own struct with its own derives, referenced by the parent. If a JSON field can hold differently-shaped objects (a tagged union), you'll often model it as a serde enum with `#[serde(tag = "...")]` or `#[serde(untagged)]` — but the generator can only infer this from samples that actually show the variants, so you may need to write the enum by hand.
Is my JSON processed locally?
Yes — everything runs in your browser with no server round-trip, so your JSON never leaves the machine. That makes it safe for internal schemas or payloads with sensitive values, and it works offline once loaded.