如何在Pydantic v2中无需自定义验证实现自定义Serde Schema?
解决方案
要实现你的需求,得给Component类正确实现Pydantic v2的核心Schema——既要支持把Component实例序列化为unique_id字符串,也要支持从unique_id字符串反序列化为Component实例,同时允许直接传入Component实例创建Machine对象。
核心思路
Pydantic的__get_pydantic_core_schema__不能只返回单纯的字符串Schema,得返回一个能处理双向转换的Schema。我们可以用core_schema.no_info_wrap_validator_function包装自定义的验证/转换逻辑,同时指定序列化规则。
完整代码实现
from pydantic import BaseModel, core_schema class Component: def __init__(self, component_id: int): self.component_id = component_id @property def unique_id(self) -> str: return f"{type(self).__name__}-{self.component_id}" @classmethod def parse(cls, unique_id: str): return cls(int(unique_id.split("-", 1)[1])) @classmethod def __get_pydantic_core_schema__(cls, source_type, handler): # 处理输入:接受Component实例直接返回,接受字符串则转换为Component def validate(value): if isinstance(value, Component): return value elif isinstance(value, str): return cls.parse(value) else: raise ValueError(f"需要Component实例或unique_id字符串,得到的是{type(value)}") # 处理输出:把Component实例转为unique_id字符串 def serialize(value): return value.unique_id # 构建核心Schema return core_schema.no_info_wrap_validator_function( validate, core_schema.union_schema([ core_schema.is_instance_schema(Component), core_schema.str_schema() ]), serialization=core_schema.plain_serializer_function_ser_schema(serialize) ) class Machine(BaseModel): part_1: Component part_2: Component part_3: Component # 测试功能 if __name__ == "__main__": # 创建Machine实例 comp1 = Component(101) comp2 = Component(102) comp3 = Component(103) machine = Machine(part_1=comp1, part_2=comp2, part_3=comp3) print("原始Machine实例:", machine) # 序列化为JSON machine_json = machine.model_dump_json(indent=2) print("\n序列化后的JSON:") print(machine_json) # 反序列化恢复实例 restored_machine = Machine.model_validate_json(machine_json) print("\n反序列化后的Machine实例:", restored_machine) print("反序列化后组件的unique_id:", restored_machine.part_1.unique_id) # 生成JSON Schema schema = Machine.model_json_schema() print("\nJSON Schema:") print(schema)
关键说明
validate函数:覆盖了两种输入场景——既接受已有的Component实例直接返回,也接受unique_id字符串并调用parse方法转换为实例,解决了创建Machine时的验证错误问题。serialize函数:明确指定序列化规则,把Component实例转为unique_id字符串,满足输出要求。union_schema:告诉Pydantic这个字段的有效值可以是Component实例或字符串,兼容两种输入方式。
内容的提问来源于stack exchange,提问作者mac01021
相关产品推荐
相关产品推荐

