继承内置list的Pydantic自定义类型实例化类型异常问题
解决Pydantic自定义List子类实例被转为普通list的问题
问题根源
Pydantic对list、dict这类序列类型有默认解析逻辑:无论输入是内置类型还是其子类实例,都会被自动转换为对应的内置类型。哪怕你的validate方法被触发且输入是ListSubclass,后续处理步骤仍会把它转成普通list。
可行解决方案
1. 在validate方法中强制返回自定义子类实例
修改validate方法,确保无论输入是什么类型,最终都返回ListSubclass实例:
from pydantic import BaseModel class ListSubclass(list): @classmethod def __get_validators__(cls): yield cls.validate @classmethod def validate(cls, v): # 先校验输入合法性 if not isinstance(v, (list, cls)): raise ValueError("输入必须是列表或ListSubclass实例") # 显式返回ListSubclass实例,覆盖Pydantic的默认转换 return cls(v) class TestModel(BaseModel): test_field: ListSubclass = ListSubclass([1,2,3]) # 验证效果 obj_default = TestModel() print(type(obj_default.test_field)) # <class '__main__.ListSubclass'> obj_custom = TestModel(test_field=ListSubclass([4,5,6])) print(type(obj_custom.test_field)) # <class '__main__.ListSubclass'>
2. Pydantic v2 专用:用PlainSerializer跳过默认转换
如果使用Pydantic v2,可通过PlainSerializer直接保留自定义子类实例,无需修改validate逻辑:
from pydantic import BaseModel, PlainSerializer, WithJsonSchema from typing import Annotated class ListSubclass(list): pass # 用Annotated包装自定义类型,指定序列化规则 CustomList = Annotated[ ListSubclass, PlainSerializer(lambda x: x, return_type=list), WithJsonSchema({"type": "array", "items": {"type": "integer"}}) ] class TestModel(BaseModel): test_field: CustomList = ListSubclass([1,2,3]) obj = TestModel(test_field=ListSubclass([4,5,6])) print(type(obj.test_field)) # <class '__main__.ListSubclass'>
核心提示
- 继承内置序列类型时,Pydantic的默认行为是标准化为内置类型,必须显式指定返回自定义实例才能保留类型
- Pydantic v1依赖
validate方法的返回值控制类型;v2可借助序列化器更灵活处理
内容的提问来源于stack exchange,提问作者Jimothy
相关产品推荐
相关产品推荐

