You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
4.4 KiB
4.4 KiB
RFC 135: 统一 API 响应格式
状态: 已实施
创建日期: 2026-01-26
作者: Kiro AI
类型: 重构
概述
实施统一的 API 响应格式,确保所有接口返回一致的数据结构,符合 api-design.md 规范要求。
背景
问题
当前所有 API 接口直接返回数据,未使用统一的响应包装格式:
# 当前实现
@router.get("/projects")
async def get_projects(...):
return {"items": [...], "total": 100} # 直接返回
规范要求
根据 api-design.md,所有接口应返回统一格式:
{
"code": 200,
"message": "Success",
"data": {
"items": [...],
"total": 100
}
}
解决方案
1. 创建统一响应模型
文件: server/app/schemas/response.py
from typing import Generic, TypeVar, Optional
from pydantic import BaseModel
T = TypeVar('T')
class ApiResponse(BaseModel, Generic[T]):
"""统一 API 响应格式"""
code: int = 200
message: str = "Success"
data: Optional[T] = None
def success_response(data=None, message="Success", code=200):
"""便捷函数:创建成功响应"""
return {"code": code, "message": message, "data": data}
def error_response(message, code=400, data=None, errors=None):
"""便捷函数:创建错误响应"""
return {"code": code, "message": message, "data": data, "errors": errors}
2. 修改所有路由
修改前:
@router.get("", response_model=ProjectListResponse)
async def get_projects(...):
result = await service.get_projects(...)
return result
修改后:
from app.schemas.response import ApiResponse, success_response
@router.get("", response_model=ApiResponse[ProjectListResponse])
async def get_projects(...):
result = await service.get_projects(...)
return success_response(data=result)
实施范围
修改的文件
新增:
server/app/schemas/response.py- 统一响应模型
修改:
server/app/schemas/__init__.py- 导出响应模型server/app/api/v1/health.py(2 个接口)server/app/api/v1/auth.py(2 个接口)server/app/api/v1/users.py(2 个接口)server/app/api/v1/folders.py(15 个接口)server/app/api/v1/projects.py(20 个接口)server/app/api/v1/ai.py(10 个接口)
总计: 51+ 个接口
修改模式
-
添加导入:
from app.schemas.response import ApiResponse, success_response -
更新 response_model:
response_model=ApiResponse[OriginalSchema] -
包装返回值:
return success_response(data=result)
响应格式示例
成功响应
单个对象:
{
"code": 200,
"message": "Success",
"data": {
"id": "123",
"name": "项目名称"
}
}
列表响应:
{
"code": 200,
"message": "Success",
"data": {
"items": [...],
"total": 100,
"page": 1,
"pageSize": 20,
"totalPages": 5
}
}
简单消息:
{
"code": 200,
"message": "Success",
"data": {
"message": "操作成功"
}
}
错误响应
{
"code": 400,
"message": "验证失败",
"data": null,
"errors": [
{
"field": "name",
"message": "名称不能为空"
}
]
}
影响分析
前端影响
修改前:
const response = await api.getProjects()
const projects = response.items // 直接访问
修改后:
const response = await api.getProjects()
const projects = response.data.items // 需要通过 data 访问
兼容性
- ❌ 不向后兼容: 前端需要同步更新
- ✅ 类型安全: TypeScript 会在编译时捕获错误
- ✅ 统一处理: 前端可以统一处理响应格式
优势
- 一致性: 所有接口返回格式统一
- 可扩展: 易于添加全局字段(如
timestamp、traceId) - 错误处理: 成功和错误响应格式一致
- 符合规范: 与
api-design.md保持一致 - 类型安全: 泛型支持确保类型正确
后续工作
- 前端适配: 更新前端 API 调用代码
- 错误处理: 统一异常处理中间件
- 文档更新: 更新 API 文档示例
- 测试: 验证所有接口返回格式
参考
api-design.md- API 设计规范- FastAPI 文档 - Response Model
- Pydantic 文档 - Generic Models