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

Pydantic V2中model_dump_json序列化子类字段丢失问题求助

Pydantic V2中List[T]序列化时root字段丢失的原因与解决办法

先复现你遇到的问题场景,方便对应理解:

from pydantic import BaseModel, RootModel
from typing import List, TypeVar, Generic

T = TypeVar('T')

class BaseItem(BaseModel):
    pass

class TT(RootModel[str]):
    root: str

class TMap(Generic[T], BaseModel):
    items: List[T]

# 直接序列化TT实例,正常输出root字段
tt = TT(root="test")
print(tt.model_dump_json())  # 输出: {"root":"test"}

# 放入TMap序列化,root字段被忽略
t_map = TMap(items=[tt])
print(t_map.model_dump_json())  # 输出: {"items":[{}]}

问题原因

Pydantic V2对泛型类型的序列化逻辑是基于静态注解类型,而非运行时的实际实例类型。当你声明List[T]时,Pydantic会按照TypeVar绑定的基类(比如上面的BaseItem)的结构来序列化列表元素,不会自动识别运行时实际传入的TT子类实例的RootModel结构,因此root字段被过滤掉了。

解决办法

办法1:直接指定具体子类类型

如果不需要泛型的灵活性,直接把TMap的items注解改为具体的子类类型:

class TMap(BaseModel):
    items: List[TT]

t_map = TMap(items=[tt])
print(t_map.model_dump_json())  # 输出: {"items":[{"root":"test"}]}

办法2:让泛型正确识别运行时类型

如果必须保留泛型特性,可以通过以下几种方式处理:

子办法2.1:用Union指定所有可能的子类

把TypeVar的范围限定为所有可能的子类Union,让Pydantic能识别到子类结构:

from typing import Union

T = TypeVar('T', bound=Union[BaseItem, TT])

class TMap(Generic[T], BaseModel):
    items: List[T]

t_map = TMap(items=[tt])
print(t_map.model_dump_json())  # 输出: {"items":[{"root":"test"}]}

子办法2.2:自定义序列化器强制按实例规则序列化

使用PlainSerializer,强制让列表元素按自身的模型规则序列化:

from pydantic import PlainSerializer
from typing import Annotated

class TMap(Generic[T], BaseModel):
    items: List[Annotated[T, PlainSerializer(lambda x: x.model_dump())]]

t_map = TMap(items=[tt])
print(t_map.model_dump_json())  # 输出: {"items":[{"root":"test"}]}

子办法2.3:开启任意类型支持并自定义Schema

如果泛型类型范围较广,可以开启arbitrary_types_allowed,并手动指定Schema:

class TMap(Generic[T], BaseModel):
    items: List[T]

    model_config = {"arbitrary_types_allowed": True}

    @classmethod
    def __get_pydantic_json_schema__(cls, schema, handler):
        schema = handler(schema)
        # 为列表元素指定实际的TT模型Schema
        schema['properties']['items']['items'] = TT.model_json_schema()
        return schema

t_map = TMap(items=[tt])
print(t_map.model_dump_json())  # 输出: {"items":[{"root":"test"}]}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 12:24:07