EN
My tools

JSON to Rust Struct Generator (serde)

Generate Rust structs with serde derives from JSON: snake_case fields with rename or rename_all, Option<T>, Vec<T>, nested structs and serde_json::Value.

Rust code
Structs generated
3

Add to Cargo.toml: serde = { version = "1", features = ["derive"] } and serde_json = "1" (to parse with serde_json::from_str, and for serde_json::Value).

serde_json::Value is used where the samples were always null, empty or of mixed kinds; replace it with a real type when you know it.

A number written with a decimal point or an exponent (10.0, 1e3) is typed f64, because serde_json does not read it into an integer field. Dates stay String (use chrono with its serde feature for date types).

My tools →
Advertisement

Rust programs read JSON with serde, which needs a struct whose fields and types match the data. Paste a sample and get ready-to-use structs: nested objects become their own structs, arrays become Vec<T>, values that are null or missing in some samples become Option<T>, and JSON names that are not snake_case are mapped with #[serde(rename_all)] or #[serde(rename)]. Keywords such as type are written as raw identifiers (r#type), which serde reads under the plain name.

How to use this tool

  1. Paste a representative JSON sample — arrays with several items give the best types.
  2. Enter the root struct name.
  3. Choose the derives and when to use Option<T>.
  4. Copy the code into your crate and add serde and serde_json to Cargo.toml.

Formula

whole number → i64 · fraction → f64 · true/false → bool · text → String · [ … ] → Vec<T> · { … } → struct · null or missing → Option<T>

Values at the same place in different samples are merged: i64 and f64 become f64; anything mixed, always null or an empty object becomes serde_json::Value. Field names are snake_case. For each struct the tool picks the serde rename_all rule (camelCase, PascalCase, kebab-case or SCREAMING_SNAKE_CASE) that matches the most keys and adds #[serde(rename = "…")] for the rest. Rust keywords become raw identifiers, except self, Self, super and crate, which get a trailing underscore and a rename. Structs with the same shape are generated once.

Example

The sample user gives three structs. User has id: i64, user_name: String, is_active: bool, balance: f64, r#type: String, tags: Vec<String>, address: Address, orders: Vec<Order> and manager: serde_json::Value, with #[serde(rename_all = "camelCase")]. Order gets coupon: Option<String>, because only the second order has a coupon.

Frequently asked questions

Why is a field serde_json::Value?

Its samples were always null, an empty object, or different kinds of values, so no single Rust type fits. Replace it with the real type once you know it.

Do I need skip_serializing_if?

Only if the JSON you write should leave out fields that are None instead of writing null. serde already reads a missing Option field as None; the default attribute added with it just makes that explicit.

Why i64 and not i32 or u32?

A sample cannot show the full range a field may take, so i64 is the safe default. Narrow it if you know the limits.

Is my JSON uploaded?

No. The code is generated in your browser.

Sources

Last updated:

Cite or embed this tool
APA

kakaoCalc. (2026, November 8). JSON to Rust Struct Generator (serde). https://kakao.mobile/tools/json-to-rust-struct/

MLA

“JSON to Rust Struct Generator (serde).” kakaoCalc, 8 Nov. 2026, kakao.mobile/tools/json-to-rust-struct/.

Paste this code into your page. The widget runs in your visitors' browsers, shows no ads and keeps a link back to this page. Embedding terms

Advertisement