JSON to Rust Struct Generator
Last updated:
Jsonic's JSON to Rust Struct generator converts a JSON object into Rust struct definitions ready for use with serde. Each struct gets #[derive(Debug, Clone, Serialize, Deserialize)] automatically. JSON strings map to String, integers to i64, decimals to f64, booleans to bool. Null values become Option<T>. Arrays become Vec<T>. Nested objects generate separate named structs declared before the root. When a JSON key differs from the Rust field name, the generator adds a #[serde(rename)] attribute. All processing runs in your browser with no data upload.
How to convert JSON to a Rust struct
- Paste your JSON object into the left panel, or click Example to load a sample.
- Optionally change the root struct name (default: Root).
- Click Generate.
- Copy the generated Rust code and add serde to your Cargo.toml: serde = { version = "1", features = ["derive"] }.
- Use serde_json::from_str::<Root>(&json_string) to deserialize your JSON.
FAQ
What serde features does the generated code require?
The generated structs use #[derive(Serialize, Deserialize)] from the serde crate with the derive feature. Add this to Cargo.toml: serde = { version = "1", features = ["derive"] }. For JSON parsing, also add: serde_json = "1". The generated code imports use serde::{Deserialize, Serialize}.
How are JSON types mapped to Rust types?
JSON strings → String, JSON integers (whole numbers) → i64, JSON decimals → f64, JSON booleans → bool, JSON null → Option<T> where T is the inferred type, JSON arrays → Vec<T>, JSON objects → named struct. When a field is null, the type becomes Option<T> and serde will set it to None when missing.
How are nullable fields handled?
A JSON field with a null value gets the type Option<T>. When deserializing with serde_json, Option fields that are missing from the JSON are set to None automatically. Add #[serde(skip_serializing_if = "Option::is_none")] manually to omit None fields from serialization output.
What are serde rename attributes used for?
When a JSON key contains characters that are invalid in Rust identifiers (like hyphens), or when the snake_case conversion changes the key (e.g. "userId" → "user_id"), the generator adds #[serde(rename = "original_key")] so serde maps the JSON field correctly.
How are nested JSON objects handled?
Each nested JSON object becomes a separate named Rust struct. Nested structs are declared before the root struct in the output so Rust can resolve the type names. The root struct references nested structs by name.
Can I use this with async frameworks like Actix-web or Axum?
Yes. The generated structs with serde derives work directly with Axum's Json<T> extractor and Actix-web's web::Json<T>. For Axum: async fn handler(Json(payload): Json<Root>) -> impl IntoResponse. The struct must implement Deserialize (already in the generated code).
Why does the generator use i64 instead of u32 or usize?
JSON integers can be negative and can exceed 32-bit range, so i64 is the safe default. If you know your values fit in a smaller type, change i64 to i32, u32, or usize after generating. serde_json will deserialize any JSON integer into i64 without truncation.
How do I add validation to the generated structs?
Use the validator crate: add #[derive(Validate)] and field-level constraints like #[validate(email)] for email fields, #[validate(range(min = 0))] for numbers, or #[validate(length(min = 1))] for strings. The generated code gives you the type definitions; add validation attributes manually.