You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SQLAlchemy自关联查询后JSON序列化遇递归错误的解决方法

解决自关联模型序列化递归错误的方案

原因分析

自关联的created_by字段会让每个User对象包含另一个User实例,而这个实例又有自己的created_by属性,序列化时会无限递归遍历这种关联关系,最终触发递归深度超限错误。

具体解决方法

方法1:序列化时直接排除关联字段

在jsonable_encoder中通过exclude参数指定排除created_by字段,避免递归遍历:

jd = jsonable_encoder(list(results), exclude_none=True, exclude={"created_by"})

如果需要保留创建者ID而非整个对象,只需保留created_by_id字段、排除created_by即可。

方法2:使用Pydantic模型控制序列化结构

定义Pydantic模型时明确指定要序列化的字段,避免包含循环引用的关联对象:

from pydantic import BaseModel

class UserResponse(BaseModel):
    id: int
    created_by_id: int | None
    # 添加其他需要返回的字段,不要包含created_by

# 序列化时转换为Pydantic模型列表
user_list = list(results)
jd = UserResponse.model_validate(user_list, many=True).model_dump(exclude_none=True)

如果需要展示创建者的基础信息,可以定义递归模型并自动处理循环:

class UserResponse(BaseModel):
    id: int
    created_by_id: int | None
    created_by: "UserResponse" | None = None

UserResponse.model_rebuild()  # 解决自引用模型的前置声明问题

jd = UserResponse.model_validate(user_list, many=True).model_dump(exclude_none=True)

Pydantic会自动处理自引用的递归序列化,不会触发深度超限。

方法3:修改SQLAlchemy查询,不加载关联对象

在查询时使用noload避免加载created_by关联,从根源上消除对象的循环引用:

query = select(User) \
    .outerjoin(alias_user.created_by) \
    .options(defer(User.hashed_password), noload(User.created_by))

查询返回的User对象不会包含created_by实例,序列化时自然不会触发递归。

内容的提问来源于stack exchange,提问作者Hatef Alipoor

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 17:42:11