FastAPI返回嵌套对象时丢失字段问题排查求助
FastAPI接口IngredientBody字段缺失问题排查与解决
FastAPI GET接口返回包含IngredientBody列表的ComponentBody时,ingredientMeasurement和ingredientUnit字段未返回,但调试确认数据库已获取到对应数据,单独返回IngredientBody列表时所有字段正常,DirectionBody无此异常。
问题根源
代码中存在字段映射不匹配的问题:
- 数据库模型
IngredientModel的字段为measurement和unit - Pydantic模型
IngredientBody对应的字段为ingredientMeasurement和ingredientUnit - Service层直接将数据库查询得到的
IngredientModel列表赋值给componentBody.componentIngredients,Pydantic自动序列化时无法识别字段映射关系,导致这两个字段未被正确转换。 - 而
DirectionBody的字段名与DirectionModel完全对应(如directionText),因此序列化正常。
解决方案
方案1:手动转换模型对象
在Service层将IngredientModel逐个转换为IngredientBody对象,明确字段映射关系:
def getComponentDetail(componentId): ingredients = componentDataProvider.findIngredientsByComponentId(componentId) directions = componentDataProvider.findDirectionsByComponentId(componentId) component = componentDataProvider.findComponentById(componentId) # 手动转换IngredientModel到IngredientBody ingredient_bodies = [ IngredientBody( ingredientId=ing.ingredientId, ingredientName=ing.ingredientName, ingredientMeasurement=ing.measurement, ingredientUnit=ing.unit ) for ing in ingredients ] componentBody = ComponentBody() componentBody.componentName = component.componentName componentBody.componentId = component.componentId componentBody.componentLink = component.originalLink componentBody.componentNotes = component.componentNotes componentBody.componentIngredients = ingredient_bodies componentBody.componentDirections = directions return componentBody
方案2:使用Pydantic字段别名
在IngredientBody中为字段添加别名,匹配数据库模型的字段名,让Pydantic自动识别映射:
from pydantic import Field class IngredientBody(BaseModel): ingredientId: int | None = None ingredientName: str ingredientMeasurement: float = Field(alias="measurement") ingredientUnit: str = Field(alias="unit") def toModel(self): model = IngredientModel() model.ingredientId = self.ingredientId model.ingredientName = self.ingredientName model.measurement = self.ingredientMeasurement model.unit = self.ingredientUnit return model
方案3:统一字段名(可选)
若项目允许,将IngredientBody的字段名修改为与IngredientModel一致,无需额外转换即可直接赋值:
class IngredientBody(BaseModel): ingredientId: int | None = None ingredientName: str measurement: float unit: str def toModel(self): model = IngredientModel() model.ingredientId = self.ingredientId model.ingredientName = self.ingredientName model.measurement = self.measurement model.unit = self.unit return model
此方案需同步修改所有使用IngredientBody的代码,适合字段名未广泛使用的场景。
验证
修改后重新运行接口,componentIngredients列表中的每个对象应包含目标字段,且值与数据库数据一致。
内容的提问来源于stack exchange,提问作者murrag
相关产品推荐
相关产品推荐

