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.
 

2.7 KiB

修复项目 API 响应序列化问题

日期: 2026-01-21
类型: Bug 修复
影响范围: 后端 API - 项目模块

问题描述

创建项目时前端收到的响应数据格式不正确,导致:

  1. 前端无法正确获取项目 ID
  2. 导航到项目详情页时使用了错误的 ID(undefined 或错误值)
  3. 后端尝试将非 UUID 字符串转换为 UUID 时抛出 500 错误

根本原因

Project 模型的 id 字段定义了 alias="project_id",但 ProjectResponse schema 期望字段名为 id。FastAPI 在序列化时使用了 alias,导致前端收到的字段名不一致。

# 模型定义
class Project(SQLModel, table=True):
    id: UUID = Field(
        sa_column=Column(...),
        alias="project_id"  # ❌ 这导致了序列化问题
    )

解决方案

在所有返回 Project 对象的 API 端点中,手动构建响应字典,确保字段名使用 camelCase 格式:

@router.post("", response_model=ProjectResponse, summary="创建项目")
async def create_project(...):
    service = ProjectService(session)
    project = await service.create_project(...)
    
    # 手动构建响应
    return {
        "id": str(project.id),  # ✅ 使用正确的字段名
        "name": project.name,
        "type": project.type_str,
        "ownerId": str(project.owner_id),
        "folderId": str(project.folder_id) if project.folder_id else None,
        # ... 其他字段
    }

修改的端点

  1. POST /api/v1/projects - 创建项目
  2. GET /api/v1/projects - 获取项目列表
  3. GET /api/v1/projects/{id} - 获取项目详情
  4. PUT /api/v1/projects/{id} - 更新项目
  5. POST /api/v1/projects/{id}/move - 移动项目
  6. PUT /api/v1/projects/{id}/order - 更新项目顺序

测试验证

  • 创建项目返回正确的 UUID
  • 项目列表返回正确的字段名
  • 项目详情返回正确的字段名
  • 更新项目返回正确的字段名
  • 前端可以正确导航到项目详情页

后续优化建议

考虑以下方案避免手动构建响应:

  1. 移除 alias:修改 Project 模型,移除 alias="project_id"
  2. 自定义序列化器:实现自定义的 Pydantic 序列化器
  3. 使用 model_dump:在 service 层返回字典而非模型实例

相关文件

  • server/app/api/v1/projects.py - 修改了 6 个端点
  • server/app/models/project.py - 问题根源(未修改)
  • server/app/schemas/project.py - Response schema 定义

影响

  • 修复了创建项目后无法跳转的问题
  • 修复了 500 错误(UUID 转换失败)
  • 统一了前后端字段命名(camelCase)
  • ⚠️ 增加了代码重复(每个端点都需要手动构建响应)