2. OpenAPI 规范基础:OpenAPI 3.0 简介、路径定义、请求/响应模型、参数校验规则
2.1 OpenAPI 3.0 简介
OpenAPI 规范(原 Swagger 规范)是一种用于描述 HTTP API 的标准化接口描述语言。OpenAPI 3.0 是目前广泛采用的版本,它允许开发者以机器可读的 YAML 或 JSON 格式定义 API 的端点、输入输出、认证方式及校验规则。在异步导出场景中,OpenAPI 规范是定义“参数校验失败”响应结构的基础契约。
核心价值: 一份 OpenAPI 3.0 文档同时驱动 API 文档生成、客户端 SDK 生成、服务端参数校验框架(如 express-openapi-validator)以及测试用例。
2.2 路径定义与操作对象
每个 API 端点通过 paths 对象定义,包含一个或多个 HTTP 方法(operation)。路径支持模板参数(如 /export/{taskId}),这些参数是参数校验的第一道关卡。
paths:
/export:
post:
summary: 发起异步导出任务
operationId: createExportTask
parameters:
- name: X-Request-Id
in: header
required: true
schema:
type: string
pattern: '^[a-f0-9\-]{36}$'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/ExportRequest'
responses:
'202':
description: 任务已接受
'400':
description: 参数校验失败
content:
application/json:
schema:
$ref: '#/components/schemas/ValidationErrorResponse'
2.3 请求/响应模型
OpenAPI 3.0 使用 components/schemas 定义可复用的数据模型。在异步导出中,请求模型定义导出参数,响应模型定义校验失败的结构。
| 模型类型 | 示例字段 | 校验关注点 |
|---|---|---|
| ExportRequest | dateFrom, dateTo, format, filters | 日期范围、枚举值、嵌套对象必填 |
| ValidationErrorResponse | code, message, errors[] | 错误码、人类可读消息、字段级错误列表 |
| FieldError | field, reason, rejectedValue | 字段路径、失败原因、被拒绝的值 |
components:
schemas:
ExportRequest:
type: object
required: [dateFrom, dateTo, format]
properties:
dateFrom:
type: string
format: date
dateTo:
type: string
format: date
format:
type: string
enum: [csv, xlsx, json]
ValidationErrorResponse:
type: object
required: [code, message, errors]
properties:
code:
type: string
example: VALIDATION_ERROR
message:
type: string
example: 请求参数校验失败
errors:
type: array
items:
$ref: '#/components/schemas/FieldError'
FieldError:
type: object
required: [field, reason]
properties:
field:
type: string
example: dateFrom
reason:
type: string
example: 日期格式无效
rejectedValue:
type: string
example: 2025-13-01
2.4 参数校验规则
OpenAPI 3.0 提供多层次的校验规则,覆盖路径参数、查询参数、请求头、请求体。在异步导出中,校验失败必须返回统一的 400 Bad Request 响应。
设计原则: 所有校验失败响应必须使用相同的
ValidationErrorResponse 模型,确保客户端解析逻辑一致。
2.4.1 校验规则分类
- 类型校验:
type(string, integer, boolean, array, object) - 格式校验:
format(date, date-time, email, uuid, uri) - 约束校验:
minimum,maximum,minLength,maxLength,pattern - 枚举校验:
enum限定允许值列表 - 必填校验:
required数组定义必填字段 - 嵌套校验:
allOf,oneOf,anyOf组合模式
2.4.2 校验失败响应结构
当参数校验失败时,服务端必须返回包含字段级错误详情的响应。以下是一个典型的校验失败响应示例:
HTTP/1.1 400 Bad Request
Content-Type: application/json
{
"code": "VALIDATION_ERROR",
"message": "请求参数校验失败",
"errors": [
{
"field": "dateFrom",
"reason": "日期格式无效,应为 yyyy-MM-dd",
"rejectedValue": "2025-13-01"
},
{
"field": "format",
"reason": "枚举值无效,允许值: csv, xlsx, json",
"rejectedValue": "pdf"
}
]
}
2.5 参数校验流程(SVG)
下图展示了从请求到达至校验失败响应的完整流程:
2.6 校验规则与响应映射(SVG)
下表以图形方式展示不同校验规则与响应中 errors[].reason 的映射关系:
2.7 最佳实践与避坑
常见陷阱: 不要在校验失败响应中返回 HTTP 200 状态码。即使业务逻辑部分成功,只要参数校验失败,必须使用 400 状态码。客户端依赖状态码判断是否重试或展示错误。
- 统一错误模型: 所有校验失败响应使用同一个
ValidationErrorResponse模型,避免不同端点返回不同结构。 - 字段路径清晰:
field使用点号路径(如filters.dateRange.start)便于客户端定位嵌套字段。 - 拒绝值保留: 在
rejectedValue中保留用户传入的原始值,方便调试和用户提示。 - 国际化准备:
message和reason使用英文或中文均可,但建议在 API 网关层统一处理国际化。 - 性能考虑: 参数校验应在请求进入业务逻辑之前完成,避免无效请求消耗数据库或文件系统资源。