JSON to Rust struct generator

Paste a JSON response and get Rust structs ready for serde_json. Fields become snake_case, keys that differ get #[serde(rename)], and values that can be null or missing become Option<T>.

Runs in your browser: nothing you enter is sent anywhere.

How to use it

  1. Paste a JSON sample. Arrays with several objects give the best result.
  2. Choose whether structs and fields are pub and whether None values are skipped when serializing.
  3. Copy the code into your crate and parse with let root: Root = serde_json::from_str(&text)?;.

How it works

The sample is read into a shape: every key with every type seen at that place. All objects of one array are merged into one struct, so a key present in only some of them becomes Option.

  • Each struct derives Debug, Clone, Serialize and Deserialize.
  • Struct names come from keys: items holds Vec, customer becomes Customer.
  • A top-level array gives a type alias, such as pub type Root = Vec;.

Worked example

{"items":[{"sku":"A","note":null,"qty":1},{"sku":"B","note":"x"}]} without pub and with Skip None gives:

use serde::{Deserialize, Serialize};

#[derive(Debug, Clone, Serialize, Deserialize)]
struct Root {
    items: Vec<Item>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
struct Item {
    sku: String,
    #[serde(skip_serializing_if = "Option::is_none")]
    note: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    qty: Option<i64>,
}

Tips

  • If every key is camelCase, you can replace the per-field renames with one #[serde(rename_all = “camelCase”)] on the struct.
  • Narrow types where you know the range: u32 for counts, u8 for small codes.
  • Add #[serde(deny_unknown_fields)] if extra keys should be an error.

Frequently asked questions

How are JSON types mapped to Rust?

Strings become String, true and false bool, whole numbers i64 and other numbers f64 (a mix of both becomes f64). Arrays become Vec<T>, objects become their own structs, and a place holding different kinds of values becomes serde_json::Value.

When is a field an Option?

When the sample has null there, or the key is missing from some objects of an array. Serde's derive reads a missing Option field as None, so no #[serde(default)] is needed.

What does Skip None when serializing do?

It adds #[serde(skip_serializing_if = "Option::is_none")] to every Option field, so serializing leaves out keys whose value is None instead of writing null.

What happens to keys like userId or type?

Fields are snake_case: userId becomes user_id with #[serde(rename = "userId")]. A Rust keyword such as type gets an underscore, type_, and a rename to the original key.

Which crates do I need?

serde with the derive feature and serde_json: in Cargo.toml, serde = { version = "1", features = ["derive"] } and serde_json = "1".

More in Developer

All tools in this category: Developer ·Updated November 4, 2026

Privacy choices

Google Analytics shows us which tools are used and whether they work. It may set cookies. Your choice is kept in this browser.