JSON to Rust Converter Online — Generate Struct + serde

Generate Rust structs from any JSON payload — #[derive(Serialize, Deserialize)] derives, snake_case field renaming, Vec<T> arrays, and nested structs ready for serde_json. 100% in your browser.

What is a JSON to Rust converter?

A JSON to Rust converter reads a JSON sample and emits typed Rust structs that mirror the JSON shape — #[derive(Serialize, Deserialize)] derives, snake_case field renaming for camelCase JSON keys, Vec<T> for arrays, and nested structs. The output drops straight into an Axum, Actix Web, Rocket, Tower, or tokio project and (de)serializes with serde_json without any extra wrappers.

Writing struct definitions by hand from a 200-field API payload wastes hours and is bug-prone — a single typo in a field name silently fails the deserialize call at runtime. OpenFormatter's converter walks the JSON tree once, generates idiomatic Rust, and runs entirely in your browser so internal API responses never leave your machine.

How to generate Rust structs from JSON — 4 steps

  1. Paste a real JSON response. Use a representative sample — type inference quality depends on it. Booleans must be true/false, numbers must be unquoted.
  2. Click Convert. The tool emits a Root struct plus one separate struct per nested object, with snake_case fields and serde renames where needed.
  3. Copy and paste into your Rust project. Each struct is independent — split them into modules under src/models/.
  4. Deserialize. let root: Root = serde_json::from_str(&data)?; — that is all serde_json needs once the struct derives Deserialize.

JSON to Rust type mapping

Sample JSON

{
  "id": 42,
  "name": "Ada Lovelace",
  "active": true,
  "score": 98.5,
  "address": { "city": "London" },
  "tags": ["admin", "engineer"]
}

Generated Rust struct

use serde::{Deserialize, Serialize};

#[derive(Debug, Serialize, Deserialize)]
pub struct Root {
    pub id: i64,
    pub name: String,
    pub active: bool,
    pub score: f64,
    pub address: Address,
    pub tags: Vec<String>,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct Address {
    pub city: String,
}

serde derive macros

#[derive(Debug, Serialize, Deserialize)] on every struct — drop the file in, add serde + serde_json to Cargo.toml, and serde_json::from_str works immediately.

snake_case + serde rename

camelCase or PascalCase JSON keys map to snake_case Rust fields with #[serde(rename = "...")] so the wire format stays intact.

Client-Side Only

JSON is parsed in JavaScript inside the browser. Internal API responses, tokens, or PII never reach a server.

Common use cases

  • check_circleGenerating Axum / Actix Web / Rocket extractors from a frontend JSON payload
  • check_circleBuilding reqwest or hyper HTTP client response types from a JSON spec
  • check_circleProducing tokio task message structs from JSON-encoded events
  • check_circleModelling Stripe, Slack, GitHub webhook payloads as serde structs
  • check_circleGenerating Cargo workspace shared types from an OpenAPI JSON example
  • check_circleBuilding Tauri command response shapes from JSON
  • check_circleModelling Solana, Ethereum, or other blockchain RPC JSON-RPC responses
  • check_circleGenerating WebAssembly module input/output types from JSON samples

Why client-side generation matters

The JSON you paste often contains real customer data, OAuth tokens, signed URLs, or internal field names you do not want indexed by a third-party converter. OpenFormatter generates the Rust entirely in JavaScript on your device — open the Network tab in DevTools and you will see zero requests when you click Convert. Safe for enterprise use, safe behind a corporate proxy, safe when the API contract is itself confidential.

Need other Rust tooling?

Format JSON, convert XML to Rust, or generate types for other systems languages — all browser-side.

Frequently Asked Questions

Does the output use serde?

Yes. Every generated struct carries #[derive(Debug, Serialize, Deserialize)] from the serde crate, so serde_json::from_str() and serde_json::to_string() work out of the box. Add serde = { version = "1", features = ["derive"] } and serde_json = "1" to your Cargo.toml. The Debug derive lets you println!("{:?}", root) for quick inspection without writing your own Display impl.

How are Option<T> types inferred?

JSON null in the sample becomes Option<serde_json::Value> by default — that is the safest fallback because serde_json::Value can carry any nested JSON shape. To pin it to a concrete type, change Option<serde_json::Value> to Option<String> or Option<i64> after copying. For fields that may be absent in the wire format (not just null) add #[serde(default)] so missing keys deserialize as Option::None.

How are Rust snake_case conventions applied?

JSON keys in camelCase or PascalCase (e.g. zipCode, UserId) are converted to snake_case Rust field names (zip_code, user_id) and tagged with #[serde(rename = "zipCode")] so serde reads and writes the original wire format. snake_case keys in the JSON pass through unchanged with no rename attribute needed.

How do I deserialize the generated structs?

let root: Root = serde_json::from_str(&json_string)?; — that is everything serde_json needs once the struct derives Deserialize. To stream from a Read use serde_json::from_reader. To convert from a serde_json::Value already in memory use serde_json::from_value(value)?.

How are JSON arrays mapped to Rust?

Arrays of objects become Vec<StructName>. Arrays of strings become Vec<String>; arrays of integers become Vec<i64>; arrays of floats become Vec<f64>. Mixed-type arrays fall back to Vec<serde_json::Value>. serde_json handles Vec<T> directly — no extra wrapper required.

Why is the tool emitting i64 instead of u64?

JSON numbers are emitted as i64 because that covers the full safe-integer range in serde_json without sign concerns. For unsigned IDs change to u64 manually. Note that JavaScript JSON parsers cap precision at 2^53 — for larger IDs (Twitter snowflake, blockchain hashes) use String and parse to u64 inside your code.

How are nested JSON objects modelled?

Each nested object becomes its own #[derive(Serialize, Deserialize)] struct so you can split the file or pull each into its own module. The parent struct holds the nested type by value (pub address: Address) — change to Option<Address> for fields that may be absent or null in the JSON.

Is the JSON uploaded to your servers?

No. Conversion runs entirely in your browser via JavaScript. Open DevTools → Network and click Convert — no requests are made. JSON containing API keys, internal field names, or PII never leaves your machine.

JSON to Rust Converter — Generate Struct + serde