Pydantic序列化自定义Python类报错,如何无需转dataclass实现?
问题解答
这是预期行为吗?
是的,这属于Pydantic的预期行为。Pydantic默认仅支持序列化自身模型类、dataclass以及Python内置基础类型(如str、int、list、dict等)。普通自定义Python类没有内置的序列化规则,Pydantic无法自动解析其内部结构,因此会抛出Unable to serialize unknown type错误。而将普通类转为dataclass后,Pydantic能识别其结构,自然可以正常序列化。
无需修改原类的序列化方案
以下几种方法可以在不改动MyObj类的前提下实现序列化:
1. 为dataclass字段添加序列化器
在MainObj中针对nested字段定义field_serializer,手动将MyObj实例转换为可序列化的字典:
# myobj.py(保持不变) class MyObj: def __init__(self, name: str, value: int): self.name = name self.value = value
# mwe.py 修改后 from dataclasses import dataclass from pydantic import TypeAdapter, field_serializer from myobj import MyObj @dataclass class MainObj: id: int nested: MyObj # 针对nested字段的序列化器 @field_serializer('nested') def serialize_nested(self, obj: MyObj) -> dict: return {"name": obj.name, "value": obj.value} MAIN_OBJ_TA = TypeAdapter(MainObj) obj = MainObj(id=1, nested=MyObj(name="test", value=2)) j = MAIN_OBJ_TA.dump_json(obj) print(j.decode())
2. 注册全局类型序列化器
如果MyObj在多个场景中被用到,可以给MyObj类型注册全局序列化规则,所有使用该类型的Pydantic场景都能自动序列化:
# mwe.py 修改后 from dataclasses import dataclass from pydantic import TypeAdapter from pydantic_core import core_schema from myobj import MyObj # 定义MyObj的序列化函数 def serialize_myobj(obj: MyObj) -> dict: return {"name": obj.name, "value": obj.value} # 注册全局序列化规则 core_schema.register_serializer(MyObj, serialize_myobj) @dataclass class MainObj: id: int nested: MyObj MAIN_OBJ_TA = TypeAdapter(MainObj) obj = MainObj(id=1, nested=MyObj(name="test", value=2)) j = MAIN_OBJ_TA.dump_json(obj) print(j.decode())
3. 用Pydantic模型包裹普通类
创建对应MyObj的Pydantic模型,通过转换函数将MyObj实例转为模型实例,间接实现序列化:
# mwe.py 修改后 from dataclasses import dataclass from pydantic import TypeAdapter, BaseModel from myobj import MyObj # 定义对应MyObj的Pydantic模型 class MyObjModel(BaseModel): name: str value: int @classmethod def from_myobj(cls, obj: MyObj): return cls(name=obj.name, value=obj.value) @dataclass class MainObj: id: int nested: MyObj # 序列化时先转换为模型 obj = MainObj(id=1, nested=MyObj(name="test", value=2)) serializable_obj = MainObj(id=obj.id, nested=MyObjModel.from_myobj(obj.nested)) MAIN_OBJ_TA = TypeAdapter(MainObj) j = MAIN_OBJ_TA.dump_json(serializable_obj) print(j.decode())
内容的提问来源于stack exchange,提问作者Sirion
相关产品推荐
相关产品推荐

