FastAPI中Pydantic无法序列化数据问题求助
FastAPI中Pydantic序列化失败问题解决
问题现象
- 路由配置
response_model=List[SProject]时,触发ResponseValidationError,提示id、title字段缺失 - 移除
response_model后,接口返回嵌套字典列表,每个元素包含Project键,对应ORM对象的序列化内容
相关代码
路由代码
@router.get('', response_model=List[SProject]) async def get_all_projects(): return await ProjectDAO.find_all()
ORM模型
class ProjectProfile(Base): __tablename__ = 'project_profile' project_id = Column(ForeignKey('projects.id'), primary_key=True) profile_id = Column(ForeignKey('profiles.id'), primary_key=True) role = Column('role', String) is_creator = Column(Boolean, default=False) class Project(Base): __tablename__ = 'projects' id = Column(Integer, primary_key=True) title = Column(String, nullable=False) description = Column(String) created_at = Column(Date, default=datetime.utcnow()) profiles = relationship('Profile', secondary='project_profile', back_populates='projects')
Pydantic Schema
class SProject(BaseModel): id: int title: str description: Optional[str] = None created_at: Optional[datetime] = None class Config: orm_mode = True
原DAO层代码
class ProjectDAO(BaseDAO): model = Project @classmethod async def find_all(cls): async with async_session_maker() as session: query = select(cls.model) result = await session.execute(query) return result.mappings().all()
错误详情
fastapi.exceptions.ResponseValidationError: 2 validation errors: {'type': 'missing', 'loc': ('response', 0, 'id'), 'msg': 'Field required', 'input': {'Project': <app.projects.models.Project object at 0x7f6d5dc95e40>}} {'type': 'missing', 'loc': ('response', 0, 'title'), 'msg': 'Field required', 'input': {'Project': <app.projects.models.Project object at 0x7f6d5dc95e40>}}
移除响应模型后的正常响应
[ { "Project": { "created_at": "2023-09-20", "id": 2, "description": "sdadasd", "title": "dasd" } } ]
问题根源
DAO层使用result.mappings().all()返回的是映射字典列表,每个字典以模型名Project为键,对应的值是ORM对象。而Pydantic的SProject开启orm_mode=True后,期望直接接收ORM对象解析,无法从{"Project": ORM对象}的嵌套结构中提取id、title等字段,导致验证失败。
解决方案
修改DAO层,使用scalars().all()替代mappings().all(),直接返回ORM对象列表:
class ProjectDAO(BaseDAO): model = Project @classmethod async def find_all(cls): async with async_session_maker() as session: query = select(cls.model) result = await session.execute(query) # 直接提取ORM对象列表 return result.scalars().all()
验证结果
修改后,路由返回的ORM对象列表会被Pydantic正确序列化,符合List[SProject]的响应模型要求,不再抛出验证错误,接口返回结构与SProject定义一致。
内容的提问来源于stack exchange,提问作者rakhovetski
相关产品推荐
相关产品推荐

