JSON 与状态
共享状态与序列化
JSON 与状态 是 CoddyKit 上的免费 Learn Rust Coding 课时。 这是第 3 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Learn Rust Coding 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Learn Rust Coding 课程共包含 4 节课。
返回 JSON
Axum 让 JSON 响应变得简单。将任何 Serialize 类型包装在 Json 中,它就会设置内容类型并序列化请求体。
use axum::Json;
use serde::Serialize;
#[derive(Serialize)]
struct User { id: u32, name: String }
async fn get_user() -> Json<User> {
Json(User { id: 1, name: "Alice".into() })
}序列化集合
可序列化项组成的 Vec 会变成 JSON 数组。无需额外处理。
use axum::Json;
use serde::Serialize;
#[derive(Serialize)]
struct Item { id: u32 }
async fn list() -> Json<Vec<Item>> {
Json(vec![Item { id: 1 }, Item { id: 2 }])
}使用普通 Rust 对 JSON 建模
JSON 序列化就是将结构体转换为字符串。使用 serde_json 时,您可以调用 to_string。下面通过手动格式展示这一思想。
struct User { id: u32, name: String }
fn to_json(u: &User) -> String {
format!("{{\"id\":{},\"name\":\"{}\"}}", u.id, u.name)
}
fn main() {
let u = User { id: 1, name: "Alice".to_string() };
println!("{}", to_json(&u));
}什么是共享状态
共享状态是每个处理函数都可以访问的数据,例如数据库连接池或配置。Axum 通过 State 提取器传递它。
定义应用状态
定义一个保存共享数据的结构体。它通常会包装一个 Arc,这样克隆成本很低。
use std::sync::Arc;
#[derive(Clone)]
struct AppState {
name: Arc<String>,
}将状态附加到路由器
将状态传递给 with_state。Axum 会保存它,并将它提供给请求该状态的处理函数。
use axum::{Router, routing::get};
async fn handler() -> &'static str { "ok" }
fn app(state: AppState) -> Router {
Router::new().route("/", get(handler)).with_state(state)
}在处理函数中读取状态
添加一个 State 参数,即可在处理函数中接收状态的克隆。
use axum::extract::State;
async fn handler(State(state): State<AppState>) -> String {
state.name.to_string()
}可变共享状态
对于会发生变化的数据,请使用 Arc 中的 Mutex 等锁来保护它。这样可以安全地进行并发修改。
use std::sync::{Arc, Mutex};
#[derive(Clone)]
struct Counter {
count: Arc<Mutex<u32>>,
}在 Mutex 后修改数据
锁定互斥锁,修改值,然后让保护对象自动释放。这个可运行示例模拟了处理函数会执行的递增操作。
use std::sync::{Arc, Mutex};
fn main() {
let count = Arc::new(Mutex::new(0u32));
{
let mut guard = count.lock().unwrap();
*guard += 1;
}
println!("count = {}", *count.lock().unwrap());
}接收并回显 JSON
组合输入和输出 JSON:反序列化请求体、转换数据,然后返回 JSON。这是一种常见的创建后响应模式。
use axum::Json;
use serde::{Serialize, Deserialize};
#[derive(Deserialize)]
struct Input { name: String }
#[derive(Serialize)]
struct Output { greeting: String }
async fn greet(Json(i): Json<Input>) -> Json<Output> {
Json(Output { greeting: format!("Hi {}", i.name) })
}使用 FromRef 提取子状态
当状态包含多个部分时,派生 FromRef,这样处理函数就可以只提取所需的部分。
use axum::extract::FromRef;
#[derive(Clone)]
struct Pool;
#[derive(Clone, FromRef)]
struct AppState {
pool: Pool,
}快速检查
测试您对 JSON 和状态的理解。
总结
您已经学习了 JSON 和共享状态:
- 将
Serialize类型包装在Json中以返回响应 - 定义一个
Clone状态结构体,通常包装Arc - 使用
with_state附加状态,使用State读取状态 - 使用
Arc<Mutex>保存可变共享数据,并使用FromRef处理子状态
下一步:使用 tower 层实现中间件。
常见问题解答
「JSON 与状态」课时是免费的吗?
是的 — 「JSON 与状态」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Learn Rust Coding 课程的其余内容,请升级到 CoddyKit PRO。 Learn Rust Coding 课程共包含 4 节课。
「JSON 与状态」这节课中我会学到什么?
共享状态与序列化 你通过在浏览器中直接运行的动手代码来练习 Learn Rust Coding,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 Learn Rust Coding 需要有经验吗?
无需任何先前经验。CoddyKit 上的 Learn Rust Coding 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 3 节课,共 4 节。
「JSON 与状态」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 Learn Rust Coding 课中编写并运行代码吗?
能。每节 Learn Rust Coding 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。