Files
label_backend/docs/superpowers/specs/2026-04-15-label-backend-swagger-annotations-design.md

9.0 KiB
Raw Blame History

label_backend Swagger 参数注解与 DTO 化设计

日期2026-04-15 范围:label_backend 对外 REST API 的 Swagger/OpenAPI 文档增强

1. 背景

当前 label_backend 已经在 Controller 层使用了 @Tag@Operation,少量 DTO 也已有 @Schema 注解,因此 Swagger 页面可以展示基础接口列表和部分对象结构。

但现状仍存在几个明显问题:

  • 很多路径参数、查询参数、表单参数缺少名称、类型、取值和含义说明
  • 多个接口仍使用 Map<String, Object>Map<String, String> 作为请求体Swagger 无法准确展示字段名、字段类型和字段说明
  • 一些固定结构响应仍以 Map<String, Object> 返回Swagger 只能显示匿名对象
  • 部分接口直接暴露实体类,而实体字段尚未补齐 Swagger 字段描述
  • 通用返回包装 Result<T>PageResult<T> 没有字段级别文档说明

用户目标很明确:在 Swagger 中看到所有接口参数的名称、类型和含义。

2. 目标

本次改造完成后,label_backend 的 Swagger 页面应满足以下目标:

  • 所有公开接口都能展示清晰的路径参数、查询参数、请求头参数、表单参数说明
  • 所有固定结构的请求体都使用 DTO 建模,并为每个字段提供名称、类型、必填性和含义说明
  • 所有固定结构的主要响应对象都能展示字段说明
  • 所有分页与统一返回包装的字段含义清晰可见
  • 不改变现有接口路径、HTTP 方法和字段名称,尽量保持对现有调用方兼容

3. 非目标

本次不做以下事情:

  • 不重构整体业务流程
  • 不调整接口 URL、HTTP 方法和权限策略
  • 不强制把所有实体类都替换成专门的 Response DTO
  • 不把完全动态的业务 JSON 全量重建成复杂深层对象,只对固定边界做显式包装
  • 不顺手做无关的代码整理或目录重构

4. 设计原则

4.1 DTO-first

凡是 Swagger 需要清楚展示字段名、字段类型和字段说明的固定结构请求体,都应优先使用 DTO而不是 Map<String, Object>

4.2 文档增强优先,行为保持不变

本次的核心是 API 契约可读性增强,因此:

  • Controller 仍调用原有 Service
  • 参数字段名保持不变
  • 业务语义、状态流转、权限校验保持不变

4.3 固定结构显式化,动态结构边界化

如果接口返回的是稳定字段集合,应使用明确 DTO 或明确对象字段注解。

如果业务内部结果本身仍是动态 JSON则至少提供一个固定外层 DTO把最外层字段含义说明清楚避免 Swagger 展示匿名 Map

4.4 最小可控改动

优先修改 Controller 入口、DTO 定义和 Swagger 展示对象,尽量不侵入 Service 深层逻辑。

5. 目标改造范围

5.1 Controller

本次覆盖以下 10 个 Controller

  • AuthController
  • CompanyController
  • ExportController
  • ExtractionController
  • QaController
  • SourceController
  • SysConfigController
  • TaskController
  • UserController
  • VideoController

5.2 通用返回模型

  • Result<T>
  • PageResult<T>

5.3 现有 DTO

  • LoginRequest
  • LoginResponse
  • SourceResponse
  • TaskResponse
  • UserInfoResponse

5.4 当前直接暴露给 Swagger 的实体

  • SysUser
  • SysCompany
  • SysConfig
  • TrainingDataset
  • ExportBatch
  • VideoProcessJob

6. DTO 改造策略

6.1 必须从 Map 重构为 DTO 的请求体

以下接口应从匿名请求体改为明确 DTO

  • TaskController#createTask
    • 新增 CreateTaskRequest
  • TaskController#reassign
    • 新增 TaskReassignRequest
  • VideoController#createJob
    • 新增 VideoProcessCreateRequest
  • VideoController#handleCallback
    • 新增 VideoProcessCallbackRequest
  • CompanyController#update
    • 新增明确请求 DTO
  • CompanyController#updateStatus
    • 新增明确请求 DTO
  • ExportController#createBatch
    • 新增明确请求 DTO
  • UserController 中如仍存在匿名请求体,也统一改成 DTO

6.2 固定结构响应优先改为 DTO

以下返回如果当前为 Map<String, Object> 但字段稳定,应收敛为 DTO

  • 导出与微调相关状态响应
  • 视频回调相关固定结构响应
  • 系统配置项列表响应

6.3 动态结果场景

ExtractionControllerQaController 可能仍涉及结构化 JSON 结果。处理原则如下:

  • 如果最外层字段稳定,则增加外层 DTO 说明
  • 如果内部 items 仍允许动态内容,则在 DTO 字段级别说明该字段承载的业务 JSON 结构

7. Swagger 注解标准

7.1 Controller 方法

每个接口方法统一遵循:

  • @Tag
  • @Operation(summary = "...", description = "...")
  • 对路径参数、查询参数、请求头参数、表单参数补 @Parameter
  • 对请求体补 @io.swagger.v3.oas.annotations.parameters.RequestBody

参数描述至少包含:

  • 参数业务含义
  • 是否必填
  • 枚举值范围或典型值
  • 分页默认值或限制条件

7.2 DTO 字段

所有公开请求/响应 DTO 字段统一使用:

  • @Schema(description = "...", example = "...")

必要时增加:

  • @NotNull
  • @NotBlank
  • @Valid

7.3 通用包装类

Result<T> 应说明:

  • code:业务状态码
  • data:接口返回主体
  • message:失败或补充说明

PageResult<T> 应说明:

  • items:当前页数据列表
  • total:总记录数
  • page:当前页码,从 1 开始
  • pageSize:每页条数

7.4 直接暴露实体

对于当前直接暴露给 Swagger 的实体类,给字段补齐 @Schema 说明,但不在本次强制转换为 Response DTO。

8. 代码组织方案

建议在 dto/ 下继续保持扁平化风格,新增与接口语义一致的请求和响应类,命名以业务动作为中心,例如:

  • CreateTaskRequest
  • TaskReassignRequest
  • VideoProcessCreateRequest
  • VideoProcessCallbackRequest
  • CompanyUpdateRequest
  • CompanyStatusUpdateRequest
  • ExportBatchCreateRequest

如果某个响应只在单个 Controller 使用,但字段固定,也放在 dto/ 下,而不是内联 Map

9. 兼容性要求

为了避免影响现有调用方,本次必须满足:

  • 接口 URL 不变
  • HTTP 方法不变
  • JSON 字段名称不变
  • Multipart 参数名不变
  • 路径参数名和查询参数名不变

DTO 只是显式建模现有契约,不是重新设计契约。

9.1 README 约束同步

本次设计不仅要求代码层落地,还要求将 Swagger/DTO 约束写入项目 README.md 的开发规范中,作为后续接口开发的长期规则。

README 中至少应明确以下要求:

  • 所有对外接口参数必须在 Swagger 中清楚展示名称、类型和含义
  • 固定结构请求体禁止继续使用匿名 Map,必须定义 DTO
  • 固定结构响应应优先显式建模,避免 Swagger 展示匿名对象
  • 通用返回体和分页包装也必须维护字段说明

10. 测试策略

由于本次会把匿名请求体改为 DTO需要用测试确认请求绑定行为没有被改坏。

测试策略如下:

  • 优先补或更新 Controller 测试
  • 覆盖 DTO 替换后的 JSON 反序列化
  • 验证关键接口的请求字段名保持不变
  • 验证原有成功路径和主要失败路径仍成立

至少应覆盖:

  • 创建任务
  • 重指派任务
  • 创建视频处理任务
  • 接收视频回调
  • 创建导出批次
  • 公司更新和状态更新

11. 风险与处理

11.1 风险:字段名不一致导致请求绑定失败

处理方式:

  • DTO 字段严格对齐当前请求 JSON 的既有字段名
  • 使用 Controller 测试验证兼容性

11.2 风险:动态 JSON 过度 DTO 化,导致业务边界变复杂

处理方式:

  • 只对固定边界建模
  • 动态业务内容保留为受控字段,不做过度深挖

11.3 风险:实体类字段太多,注解工作量大

处理方式:

  • 只处理当前实际暴露到 Swagger 的实体
  • 优先处理高频接口涉及对象

12. 实施顺序

推荐按以下顺序实施:

  1. Result<T>PageResult<T> 补齐字段说明
  2. 给已有公开 DTO 补齐 @Schema
  3. 将匿名请求体改造成 DTO并更新对应 Controller
  4. 将固定结构的 Map 响应改造成 DTO
  5. 为直接暴露的实体补齐 @Schema
  6. 统一补齐 Controller 参数 @Parameter 注解
  7. 更新或新增相关测试并执行验证

13. 验收标准

验收通过应满足以下条件:

  • Swagger 页面中所有公开接口参数都能看到名称、类型和含义
  • 所有固定结构请求体不再以匿名 Map 展示
  • 主要响应对象字段说明齐全
  • 通用返回体字段说明齐全
  • README.md 已写入 Swagger/DTO 文档约束
  • Controller 相关测试通过
  • 未引入接口路径或字段名兼容性破坏

14. 决策总结

本次采用“DTO-first API 文档化”方案:

  • 请求体优先 DTO 化
  • 固定结构响应优先显式建模
  • Controller 参数注释统一化
  • 通用返回体和当前暴露实体补齐 Swagger 字段说明
  • 在不改变业务语义的前提下,最大化提升 Swagger 可读性和接口契约清晰度