Rust 用 utoipa 给 Axum 自动生成 OpenAPI 文档与 Swagger UI:代码即文档,无需手写
test12026-11-020 次阅读
文档不该靠手维护
Go 那边可以规范生成代码,Rust 这边走“代码即文档”更顺手。utoipa 用 derive 宏在结构体和方法上标注 schema,再配合 utoipa-swagger-ui 直接挂一个可交互的 Swagger 页面。改了结构体字段,文档自动跟着变,不会出现代码改了文档没动的情况。
定义带 schema 的结构体与接口
use axum::{routing::get, Json, Router};
use serde::{Deserialize, Serialize};
use utoipa::{OpenApi, ToSchema};
use utoipa_swagger_ui::SwaggerUi;
#[derive(Serialize, Deserialize, ToSchema)]
struct Article {
id: i64,
#[schema(example = "示例标题")]
title: String,
author: Option<String>,
}
#[utoipa::path(
get,
path = "/articles/{id}",
params(("id" = i64, Path, description = "文章 ID")),
responses((status = 200, description = "OK", body = Article))
)]
async fn get_article(id: i64) -> Json<Article> {
Json(Article { id, title: "示例标题".into(), author: Some("张三".into()) })
}
#[derive(OpenApi)]
#[openapi(paths(get_article), components(schemas(Article)))]
struct ApiDoc;
把 Swagger UI 挂到路由
#[tokio::main]
async fn main() {
let app = Router::new()
.route("/articles/{id}", get(get_article))
.merge(SwaggerUi::new("/swagger-ui")
.url("/api-docs/openapi.json", ApiDoc::openapi()));
let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();
axum::serve(listener, app).await.unwrap();
}
启动后访问 /swagger-ui 就能看到自动生成的交互式文档,能直接填参数发请求。openapi.json 也可以单独导出交给前端或网关做契约校验。
几个实用技巧
- 用 #[schema(example = ...)] 给字段加示例值,Swagger 里点一下就填好了,联调体验更好。
- 枚举和可选字段直接靠 serde 的 skip_serializing_if 与 utoipa 的 required 推断,文档与运行时语义一致。
- CI 里加一步导出 openapi.json 并提交,等于把“接口契约”纳入版本管理,前后端照着同一份跑。
T
test1
文章作者
文档不该靠手维护 Go 那边可以规范生成代码,Rust 这边走“代码即文档”更顺手。utoipa 用 derive 宏...
- 分类
- 技术
- 发布时间
- 2026-11-02
- 字数
- 约 1535 字
- 阅读
- 0 次
