全书目录

第三十九篇:Axum 完全指南 —— Rust 类型关口宇宙

第七章:JSON 请求体 —— 它只是“申报单反序列化”,不是一整套政务大厅魔法

1 分钟 287 字 第 753 / 962 个阅读单元

很多人从 FastAPI、NestJS、Spring 那边转来,容易误解 Axum 的 Json<T>

要记住:

Json<T> 的核心工作,是把请求体按 serde::Deserialize 反序列化成 T

它很强,但它不是“自动帮你做完所有业务校验”。

看一个标准例子:

rust
use axum::{
    extract::{State, Path},
    http::StatusCode,
    response::{IntoResponse, Response},
    Json,
};
use serde::{Deserialize, Serialize};
use std::{collections::HashMap, sync::Arc};
use tokio::sync::RwLock;

#[derive(Clone, Default)]
struct AppState {
    permits: Arc<RwLock<HashMap<u64, Permit>>>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
struct Permit {
    id: u64,
    owner: String,
    zone: String,
    status: String,
}

#[derive(Debug, Deserialize)]
struct CreatePermit {
    owner: String,
    zone: String,
}

#[derive(Debug)]
enum ApiError {
    NotFound,
    BadRequest(&'static str),
}

impl IntoResponse for ApiError {
    fn into_response(self) -> Response {
        let (status, message) = match self {
            Self::NotFound => (StatusCode::NOT_FOUND, "报关单不存在"),
            Self::BadRequest(msg) => (StatusCode::BAD_REQUEST, msg),
        };

        (
            status,
            Json(serde_json::json!({
                "error": message
            })),
        )
            .into_response()
    }
}

async fn create_permit(
    State(state): State<AppState>,
    Json(input): Json<CreatePermit>,
) -> Result<(StatusCode, Json<Permit>), ApiError> {
    if input.owner.trim().len() < 2 {
        return Err(ApiError::BadRequest("owner 太短"));
    }

    let mut permits = state.permits.write().await;
    let id = permits.len() as u64 + 1;

    let permit = Permit {
        id,
        owner: input.owner,
        zone: input.zone,
        status: "pending".to_owned(),
    };

    permits.insert(id, permit.clone());

    Ok((StatusCode::CREATED, Json(permit)))
}

这段代码里要看清三层:

  • Json<CreatePermit> 负责把申报单读出来
  • 业务语义校验由你自己决定怎么做
  • 最终放行回执由 IntoResponse 体系兜底

所以 Axum 和某些“强声明即强校验即强文档”的框架不同:

text
Axum 默认提供:
- 请求提取
- 反序列化
- 拒绝机制
- 响应转换

Axum 默认不直接替你提供:
- 业务规则校验体系
- OpenAPI 自动全家桶
- ORM
- DI 容器

这不是它弱,而是它的哲学:

海关负责验格式,不替你定义整部国家商检法。