JSON 转 Rust
暂无内容
免费在线 JSON 转 Rust 工具,粘贴 API 响应 JSON 自动生成带 Serde derive 的 struct,嵌套对象独立拆分,Vec 与 Option 智能推断,纯浏览器本地转换,无需注册。
暂无内容
免费在线 JSON 转 Rust 工具,粘贴 API 响应 JSON 自动生成带 Serde derive 的 struct,嵌套对象独立拆分,Vec 与 Option 智能推断,纯浏览器本地转换,无需注册。
JSON 转 Rust 是把 JSON 格式的数据(对象或数组)转换为 Rust struct 类型定义的过程。Rust 是一门强类型系统编程语言,广泛用于后端服务、CLI 工具、WebAssembly、嵌入式和区块链等场景。开发中经常需要把 API 文档或实际响应中的 JSON 样本转成 Rust 类型,手写 struct 不仅重复劳动多,还容易把字段类型写错,本工具的目标就是把这一过程自动化,让开发者专注业务逻辑。
本工具基于 quicktype-core 在浏览器本地运行,使用 just-types 和 no-comments 渲染选项,为 Rust 生成纯净的结构体代码。输出包含 use serde::{Serialize, Deserialize}; 和对应的 #[derive(Serialize, Deserialize)],可以直接配合 serde_json 做反序列化。这意味着你拿到的不只是类型草稿,而是能够放进 Cargo 项目、稍加依赖配置即可编译运行的 Rust 代码。
类型推断是 JSON 转 Rust 的核心。工具会把 JSON 的基本类型映射到 Rust 的标准类型:字符串映射为 String,整数映射为 i64,浮点数映射为 f64,布尔值映射为 bool,数组映射为 Vec<T>,嵌套对象映射为独立的 struct,null 值映射为 Option<serde_json::Value>。对于嵌套对象,工具会自动为每个层级创建新的 struct,并按字段名首字母大写命名,例如 address 字段会生成 Address 结构体,items 数组中的对象会生成 Item 结构体。
与一些需要把 JSON 上传到服务器处理的在线工具不同,本工具的所有计算都在浏览器内完成。quicktype-core 通过 Web Worker 加载和执行,JSON 解析、类型推断、Rust 代码生成、文件下载都在本地进行,不向任何服务器发送数据。这对于包含 API key、用户隐私字段或未上线业务结构的 JSON 尤其重要,关闭页面后数据即从内存中清除,是企业内网 JSON 反序列化的安全选择。
生成后的代码通常需要放到 Cargo 项目中使用。你需要在 Cargo.toml 中添加 serde = { version = "1", features = ["derive"] } 和 serde_json = "1" 依赖,然后把生成的 struct 复制到 src 目录下的 .rs 文件中,通过 mod 声明引入。之后就可以用 serde_json::from_str::<User>(&json_string) 把真实 API 响应转换成强类型结构体,享受 Rust 编译期的类型检查。对于 Actix-web、axum、Rocket、Warp 等主流 Rust Web 框架,生成的 struct 可直接作为 handler 参数与响应模型使用。
需要注意的是,自动生成的代码是起点而不是终点。工具按 JSON 样本推断类型,无法判断业务上的精确类型(例如 URL、Email、ID、时间戳等语义类型都会被统一推断为 String 或 i64)。对于 snake_case 的 JSON 字段,Rust struct 字段会保持原样生成,你可能需要手动添加 #[serde(rename = "user_name")] 来保持反序列化映射,或把 String 改为 chrono::DateTime<Utc>、uuid::Uuid、url::Url 等语义类型。建议把生成结果作为初稿,再根据项目规范微调字段名、类型和注解。
用 Actix-web 4.x 把生成的 struct 作为 web::Json<T> 参数,HTTP POST 请求体自动反序列化。
// Cargo.toml
// [dependencies]
// actix-web = "4"
// serde = { version = "1", features = ["derive"] }
// serde_json = "1"
use actix_web::{web, App, HttpServer, HttpResponse, Responder};
use serde::{Deserialize, Serialize};
// 由本工具自动生成(from JSON)
#[derive(Serialize, Deserialize, Debug)]
pub struct CreateUserRequest {
name: String,
email: String,
age: i64,
tags: Vec<String>,
}
#[derive(Serialize, Deserialize, Debug)]
pub struct User {
id: i64,
name: String,
email: String,
age: i64,
tags: Vec<String>,
}
// Actix-web handler:JSON 入参自动反序列化
async fn create_user(payload: web::Json<CreateUserRequest>) -> impl Responder {
let req = payload.into_inner();
let user = User {
id: 1,
name: req.name,
email: req.email,
age: req.age,
tags: req.tags,
};
HttpResponse::Ok().json(user) // 响应也用 serde_json 序列化
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
HttpServer::new(|| {
App::new()
.route("/users", web::post().to(create_user))
})
.bind("127.0.0.1:8080")?
.run()
.await
}
/*
* 客户端调用:
* curl -X POST http://127.0.0.1:8080/users \
* -H "Content-Type: application/json" \
* -d '{"name":"Alice","email":"alice@example.com","age":30,"tags":["rust","actix"]}'
*/axum 服务端用 Json<T> extractor,reqwest 客户端用 .json::<T>() 反序列化响应,生成的 struct 双向兼容。
// Cargo.toml
// [dependencies]
// axum = "0.7"
// tokio = { version = "1", features = ["full"] }
// serde = { version = "1", features = ["derive"] }
// serde_json = "1"
// reqwest = { version = "0.12", features = ["json"] }
use axum::{routing::get, Json, Router};
use serde::{Deserialize, Serialize};
// 由本工具自动生成
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct Address {
city: String,
zip: String,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct User {
id: i64,
name: String,
email: String,
address: Address,
tags: Vec<String>,
}
// axum handler:返回 JSON 响应
async fn get_user() -> Json<User> {
Json(User {
id: 1,
name: "Alice".into(),
email: "alice@example.com".into(),
address: Address { city: "Beijing".into(), zip: "100000".into() },
tags: vec!["rust".into(), "axum".into()],
})
}
// reqwest 客户端:反序列化远程 API 响应
async fn fetch_user(url: &str) -> Result<User, reqwest::Error> {
let user: User = reqwest::get(url).await?.json().await?;
Ok(user)
}
#[tokio::main]
async fn main() {
// 启动 axum 服务
let app = Router::new().route("/user", get(get_user));
let listener = tokio::net::TcpListener::bind("127.0.0.1:8080").await.unwrap();
axum::serve(listener, app).await.unwrap();
}
/*
* 编译后访问:
* curl http://127.0.0.1:8080/user
* {"id":1,"name":"Alice","email":"alice@example.com",
* "address":{"city":"Beijing","zip":"100000"},
* "tags":["rust","axum"]}
*/当 JSON 字段为 snake_case 而 Rust 字段想用 camelCase 时,通过 #[serde(rename)] 显式映射,并替换语义类型为 chrono::DateTime。
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, Debug)]
pub struct Article {
#[serde(rename = "article_id")]
pub article_id: i64,
#[serde(rename = "title")]
pub title: String,
// JSON: "2026-07-08T10:00:00Z" → chrono::DateTime<Utc>
#[serde(rename = "created_at")]
pub created_at: DateTime<Utc>,
#[serde(rename = "view_count")]
pub view_count: i64,
// 缺失字段使用 Default::default()
#[serde(rename = "summary", default)]
pub summary: Option<String>,
#[serde(rename = "tags")]
pub tags: Vec<String>,
}
fn main() -> Result<(), serde_json::Error> {
let json = r#"{
"article_id": 42,
"title": "Hello Rust",
"created_at": "2026-07-08T10:00:00Z",
"view_count": 1024,
"tags": ["rust", "serde"]
}"#;
let article: Article = serde_json::from_str(json)?;
println!("{:?}", article);
// Article { article_id: 42, title: "Hello Rust",
// created_at: 2026-07-08T10:00:00Z, view_count: 1024, ... }
// 反向序列化:Rust 值 → JSON 字符串
let s = serde_json::to_string(&article)?;
println!("{}", s);
Ok(())
}
/*
* Cargo.toml 依赖:
* serde = { version = "1", features = ["derive"] }
* serde_json = "1"
* chrono = { version = "0.4", features = ["serde"] }
*/把生成的 struct 作为 Tauri #[tauri::command] 的入参类型,前端 invoke 时按 JSON 自动反序列化。
// Cargo.toml
// [dependencies]
// tauri = { version = "2", features = [] }
// serde = { version = "1", features = ["derive"] }
// serde_json = "1"
use serde::{Deserialize, Serialize};
// 由本工具自动生成
#[derive(Serialize, Deserialize, Debug)]
pub struct CreateNoteRequest {
pub title: String,
pub content: String,
pub tags: Vec<String>,
}
#[derive(Serialize, Deserialize, Debug)]
pub struct Note {
pub id: i64,
pub title: String,
pub content: String,
pub tags: Vec<String>,
pub created_at: String, // 可手动改为 chrono::DateTime<Utc>
}
// Tauri command:前端通过 invoke('create_note', payload) 调用
#[tauri::command]
fn create_note(payload: CreateNoteRequest) -> Result<Note, String> {
let note = Note {
id: 1,
title: payload.title,
content: payload.content,
tags: payload.tags,
created_at: "2026-07-14T10:00:00Z".to_string(),
};
Ok(note)
}
#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
tauri::Builder::default()
.invoke_handler(tauri::generate_handler![create_note])
.run(tauri::generate_context!())
.expect("error while running tauri application");
}
/*
* 前端调用示例 (TypeScript):
*
* import { invoke } from '@tauri-apps/api/core';
* const note = await invoke<Note>('create_note', {
* payload: { title: 'Hello', content: 'World', tags: ['rust', 'tauri'] }
* });
*/工具按 JSON 样本推断为 String / i64 / f64 等基础类型,但业务上有 chrono::DateTime<Utc>、uuid::Uuid、url::Url、std::net::IpAddr、rust_decimal::Decimal 等更精确的语义类型。建议生成后立即把这些字段改为业务类型,让类型系统捕获更多错误。
不要把生成的 user_name 字段改名为 userName 来适配 Rust 命名规范,这会让 Serde 反序列化失败。正确做法是保留 snake_case 字段名 + #[serde(rename = "userName")],或在整个 struct 上加 #[serde(rename_all = "camelCase")]。
为向后兼容 API 版本迭代(新增字段不会让旧客户端反序列化失败),建议对所有 Option<T> 字段或允许缺省的字段加上 #[serde(default)]。这样即使 JSON 缺失该字段,也能用 Default::default() 兜底,避免反序列化整个请求失败。
虽然工具完全本地运行不发送任何数据,但粘贴前建议把 API key、access_token、用户身份证号等敏感字段脱敏或删除,避免误关浏览器后内存中残留(虽然关闭页面即清除)。这是良好的安全卫生习惯。
当 JSON 嵌套层级 ≥ 3 时,工具会生成多个嵌套 struct。建议把根 struct 放在 src/models/user.rs,嵌套 struct(如 Address、Company)放在 src/models/ 子目录,再通过 mod 声明组织,便于大型项目维护。
生成的代码默认符合 Rust 规范,但 clippy 可能提示一些改进(如建议把 String 改为 &str、把 i64 改为 usize 等)。运行 cargo clippy --all-targets -- -D warnings 可以发现潜在的类型优化点。
本工具生成的 struct 默认使用 String / Vec<T>,依赖 std 的堆分配。在嵌入式 / no_std 环境中,需要手动替换为 &'static str、heapless::String、NVec<T, N> 等无堆分配类型,并确保对应类型实现了 serde::Deserialize。
单个 JSON 超过 5MB 时,浏览器 WASM 处理会变慢且内存占用高。建议:① 按业务模块拆分 JSON;② 用本工具分别转换每个模块;③ 在 Cargo 项目中重新组合。这样既保证转换速度,也便于代码维护。
在左侧编辑器粘贴 JSON 内容,或点击上传按钮选择 .json / .txt 文件,也可以点击「Sample」加载中文示例。工具会在 400ms 内自动调用 quicktype-core 生成 Rust 代码,右侧显示带 Serde derive 的 struct。如 JSON 格式错误,可点击「修复 JSON」按钮自动修复后再转换。
包含。工具使用 quicktype-core 的 just-types 渲染模式,为 Rust 生成 use serde::{Serialize, Deserialize}; 和 #[derive(Serialize, Deserialize)],可直接配合 serde_json 做反序列化。如果你不需要 Serde,可手动移除 derive 和 use 语句。
支持所有合法 JSON 结构:基本类型(null、boolean、number、string)、数组(一维或多维)、嵌套对象(任意深度)。JSON 对象会生成根 struct,JSON 数组会生成 Vec<T> 类型的根类型。不支持 JavaScript 对象字面量、函数、Symbol、undefined 等非 JSON 值。
字符串映射为 String,整数映射为 i64,浮点数映射为 f64,布尔值映射为 bool,数组映射为 Vec<T>,嵌套对象映射为独立 struct,null 映射为 Option<serde_json::Value>。具体映射规则可参考页面下方的「JSON 类型到 Rust 类型映射速查表」。
JSON 中的 null 值会生成 Option<serde_json::Value>,表示该字段可能缺失或类型不确定。如果你已经知道字段实际类型,可在源 JSON 中给出一个示例值(如 "field": "" 推断为 String),生成后再根据业务需求改为 Option<String>、Option<i64> 等更精确的类型。
会。JSON 数组统一转换为 Rust Vec<T> 泛型,元素类型按数组首项自动推断。例如 ["a","b"] 生成 Vec<String>,[1,2,3] 生成 Vec<i64>,[{...},{...}] 生成 Vec<Item>。空数组 [] 默认生成 Vec<serde_json::Value>,生成后可根据上下文手动改为具体类型。
每个嵌套对象都会生成独立的 struct,命名规则为字段名首字母大写。例如根对象包含 address 字段,会同时生成 Root 和 Address 两个结构体,Root 中通过 address: Address 引用。相同结构的对象会被复用同一类型,避免重复定义。
quicktype-core 默认使用 JSON 源名称(如 User)作为根结构体名。你可以在生成后手动修改 struct 名称及引用位置。下载的 .rs 文件名同样可在保存时按需重命名。如果你希望工具自动按某个字段命名,可以先调整 JSON 顶层 key 再粘贴。
可以直接使用,但需确保项目已引入 serde 和 serde_json 依赖。在 Cargo.toml 中添加 serde = { version = "1", features = ["derive"] } 和 serde_json = "1",即可用 serde_json::from_str::<User>(&json) 或 serde_json::from_reader(reader) 反序列化生成的结构体。
可以。Actix-web 4.x 和 axum 0.7+ 的 JSON extractor 都基于 serde_json,生成的 struct 直接作为 handler 参数即可。例如在 axum 中:async fn create_user(Json(payload): Json<CreateUserRequest>) -> ...;在 Actix-web 中:web::Json<CreateUserRequest>。无需额外注解。
可以。reqwest 的 response.json::<T>() 内部调用 serde_json,传入生成的 struct 类型即可:let user: User = reqwest::get(url).await?.json().await?;。如果后端 API 字段名是 snake_case 而 Rust 字段是 camelCase,可手动加 #[serde(rename = "user_name")]。
支持。Tauri 的 command 函数参数通过 serde 反序列化,把生成的 struct 作为参数类型即可:#[tauri::command] fn create_user(payload: CreateUserRequest) -> Result<User, String>。Tauri 前端 JS 调用 invoke('create_user', payload) 时 payload 会自动序列化为 JSON 再在 Rust 侧反序列化。
工具默认生成 String 与 i64 等基础类型。如需 chrono::DateTime<Utc>、uuid::Uuid、url::Url、std::net::IpAddr 等语义类型,可在生成后手动调整字段类型。这些类型都实现了 Serde 的 Deserialize,只需 use chrono::{DateTime, Utc}; 后即可编译。
完全本地浏览器运行。JSON 解析、Rust 代码生成、文件下载全部在浏览器内通过 JavaScript 与 quicktype-core Web Worker 完成,输入的 JSON 数据和生成的 Rust 代码都不会上传到任何服务器,也不会被记录或缓存到云端。包含 API key、token、未公开业务字段的敏感 JSON 可以放心使用,关闭页面即清除。
不需要。工具完全免费,无需注册、登录或授权。打开页面即可使用,所有功能在浏览器本地可用。
工具会自动检测 JSON 合法性,错误时会在右侧显示红色错误提示,并提供「修复 JSON」按钮。点击后可自动修复常见错误:末尾多余逗号、单引号替换为双引号、缺失引号的 key 补全引号、注释移除等。修复成功后会继续生成 Rust 代码。
工具无显式行数限制,但浏览器对超大 JSON 的解析和渲染会变慢。建议:① 拆分 JSON 后分批转换;② 一次只关注一个嵌套层级;③ 如需批量生成 100+ 结构体,建议使用 quicktype 命令行工具(npm i -g quicktype)或 IDE 插件处理。
两者都是把 JSON 转成目标语言的类型定义,但输出形态不同:JSON 转 Rust 生成的是带 Serde derive 的 struct,属于运行时可反序列化的数据模型;JSON 转 TypeScript 生成的是 interface / type 类型声明,仅用于编译期类型检查。选择取决于你的技术栈与运行场景。
结构定义本身可以 no_std(仅依赖 core 而非 std)。但 serde_json 在 no_std 下需要使用 serde_json::de::from_slice 并启用相应 feature,且不能使用 String(需替换为 &str 或 heapless::String)。在嵌入式场景中通常需要手工调整字段类型与分配器。
工具会保持 JSON 原始字段名(包括 snake_case),Rust 字段默认遵循 snake_case 命名规范,因此与 JSON 同名时不会出现不一致。如果出现字段名差异,通常是因为源 JSON 含特殊字符或重复 key 被合并,建议先在 JSON 修复工具中清洗后再转换。
工具根据 JSON 值的类型自动推断对应的 Rust 类型:
| JSON 值示例 | 生成 Rust 类型 | 说明 |
|---|---|---|
null | Option<serde_json::Value> | null 值类型不确定,用 Option 包装 serde_json::Value 兜底 |
true / false | bool | JSON 布尔值直接映射为 Rust bool |
42 | i64 | JSON 整数默认映射为 i64(按需手动改为 u32 / usize 等) |
3.14 | f64 | JSON 浮点数默认映射为 f64(高精度场景建议 f64) |
"hello" | String | JSON 字符串映射为 Rust String(可手动改为 &str / chrono::DateTime / uuid::Uuid) |
["a","b"] | Vec<String> | 字符串数组映射为 Vec<String> |
[1,2,3] | Vec<i64> | 整数数组映射为 Vec<i64> |
[{...},{...}] | Vec<Item> | 对象数组按首个元素生成对应 struct,再用 Vec 包装 |
[] | Vec<serde_json::Value> | 空数组无法推断元素类型,用 serde_json::Value 兜底,生成后建议手动改为具体类型 |
{...} 嵌套对象 | 独立 struct | 嵌套对象生成独立 struct,字段名首字母大写命名(如 address → Address) |
{ "key": null } | Option<serde_json::Value> | 字段值为 null 时默认推断为 Option<serde_json::Value>,可手动改为 Option<String> |
quicktype-core 为 Rust 生成的典型代码包含以下部分:
| 代码部分 | 示例 | 作用 |
|---|---|---|
use serde::{Serialize, Deserialize}; | use serde::{Serialize, Deserialize}; | 引入 Serde 的序列化和反序列化 trait |
#[derive(Serialize, Deserialize)] | #[derive(Serialize, Deserialize)] | 让编译器自动生成 Serde trait 实现 |
pub struct User | pub struct User { id: i64 } | 定义公开的结构体及字段 |
Vec<T> 字段 | scores: Vec<i64> | 表示 JSON 数组字段 |
Option<T> 字段 | label: Option<serde_json::Value> | 表示可能为 null 的字段 |
嵌套 struct 引用 | address: Address | 表示嵌套对象,类型由工具自动生成 |
生成的 struct 可直接用于以下 Rust 生态的常见场景:
| 框架 / 工具 | 用法示例 | 需要依赖 |
|---|---|---|
Actix-web 4.x | web::Json<User> | actix-web = "4", serde_json = "1" |
axum 0.7 | Json<User> | axum = "0.7", serde_json = "1", tokio = "1" |
Rocket 0.5 | Json<User> | rocket = { version = "0.5", features = ["json"] } |
warp 0.3 | body::json::<User>() | warp = "0.3", serde_json = "1" |
reqwest 0.12 | response.json::<User>().await | reqwest = { version = "0.12", features = ["json"] } |
Tauri 2.x | fn command(payload: User) | tauri = "2", serde = { version = "1", features = ["derive"] } |
Bevy 0.14 | Resource / Component 序列化 | bevy = "0.14", serde = { version = "1", features = ["derive"] } |
SQLx 0.7 | FromRow + serde 字段 | sqlx = { version = "0.7", features = ["runtime-tokio", "postgres"] } |
本工具默认只生成 #[derive(Serialize, Deserialize)],但实际项目中常需额外属性注解以适配业务场景:
| 属性 | 作用域 | 作用 |
|---|---|---|
#[serde(rename = "userName")] | 字段 | 反序列化时按 JSON 原名匹配(snake_case ↔ camelCase) |
#[serde(rename_all = "camelCase")] | struct | 批量将所有字段映射为 camelCase(影响序列化与反序列化) |
#[serde(default)] | 字段 | JSON 缺失该字段时使用 Default::default() 兜底 |
#[serde(skip_serializing_if = "Option::is_none")] | 字段 | None 时不序列化该字段(用于清理 JSON 输出) |
#[serde(skip)] | 字段 | 完全跳过该字段(不进 JSON 也不从 JSON 反序列化) |
#[serde(flatten)] | 字段 | 把内嵌 struct 的字段平铺到外层 JSON(适用于动态字段) |
#[serde(deny_unknown_fields)] | struct | JSON 含未声明字段时反序列化失败(严格模式) |
#[serde(tag = "type")] | enum | 用 JSON 字段区分 enum 变体(内部标签模式) |
#[serde(untagged)] | enum | 按 JSON 内容推断 enum 变体(无标签模式) |
#[serde(alias = "user_name")] | 字段 | 为字段添加额外反序列化别名(兼容多个 JSON key) |
本 JSON 转 Rust 工具所有操作完全在你的浏览器本地完成:JSON 解析、Rust 代码生成、文件下载全部通过 quicktype-core WebAssembly 模块在客户端执行,不会通过网络向任何服务器发送 JSON 内容、上传的文件或生成的代码。文件上传使用浏览器原生 FileReader API 直接读取到内存,不经过任何中间服务。不使用 Cookie 追踪,不收集任何用户输入或使用数据。关闭或刷新页面后,所有输入和输出内容自动从内存清除。适合处理含 API 密钥、token、用户隐私数据、未上线业务结构、内部接口字段的敏感 JSON。