为Pydantic添加quantiphy.Quantity数据类型的序列化反序列化支持
解决Pydantic处理quantiphy.Quantity类型的序列化/反序列化问题
问题原因
Pydantic v2无法自动为quantiphy.Quantity生成核心Schema,且旧版的json_encoders仅负责序列化阶段,无法解决Schema生成失败的报错,必须明确指定该类型的双向转换规则(字符串转Quantity、Quantity转字符串)。
解决方案:使用Annotated+Validator/Serializer(Pydantic v2推荐方式)
通过Annotated结合BeforeValidator(反序列化)和PlainSerializer(序列化),为Quantity类型定义完整的转换逻辑,让Pydantic能正确生成Schema并处理双向转换。
完整代码示例
from pydantic import BaseModel, BeforeValidator, PlainSerializer, Annotated from quantiphy import Quantity # 定义反序列化函数:字符串转Quantity def str_to_quantity(value): if isinstance(value, str): return Quantity(value) return value # 定义序列化函数:Quantity转字符串 def quantity_to_str(quantity): return str(quantity) # 封装带转换规则的Annotated类型 QuantityStr = Annotated[ Quantity, BeforeValidator(str_to_quantity), PlainSerializer(quantity_to_str, return_type=str) ] class SpecLimit(BaseModel): label: str minimum: QuantityStr | None = None maximum: QuantityStr | None = None typical: QuantityStr | None = None is_informative: bool = False # 测试序列化 spec = SpecLimit(label="Voltage", minimum=Quantity("5V"), maximum=Quantity("10V")) print(spec.model_dump_json(indent=2)) # 输出: # { # "label": "Voltage", # "minimum": "5 V", # "maximum": "10 V", # "typical": null, # "is_informative": false # } # 测试反序列化 json_data = '''{ "label": "Current", "minimum": "2A", "typical": "3.5A" }''' spec2 = SpecLimit.model_validate_json(json_data) print(f"minimum值类型:{type(spec2.minimum)},值:{spec2.minimum}") # 输出:minimum值类型:<class 'quantiphy.quantiphy.Quantity'>,值:2 A
替代方案:使用TypeAdapter
如果需要在多个模型中复用Quantity的转换规则,可以定义TypeAdapter,然后通过Field指定:
from pydantic import BaseModel, TypeAdapter, Field from quantiphy import Quantity # 定义转换函数(同前) def str_to_quantity(value): if isinstance(value, str): return Quantity(value) return value def quantity_to_str(quantity): return str(quantity) # 创建TypeAdapter quantity_adapter = TypeAdapter( Annotated[Quantity, BeforeValidator(str_to_quantity), PlainSerializer(quantity_to_str)] ) class SpecLimit(BaseModel): label: str minimum: Quantity | None = Field(default=None, adapter=quantity_adapter) maximum: Quantity | None = Field(default=None, adapter=quantity_adapter) typical: Quantity | None = Field(default=None, adapter=quantity_adapter) is_informative: bool = False
为什么旧方法无效
json_encoders在Pydantic v2中已被废弃,且仅能处理序列化时的格式转换,无法帮助Pydantic生成Quantity类型的核心Schema,因此会出现PydanticSchemaGenerationError报错。
内容的提问来源于stack exchange,提问作者slarag
相关产品推荐
相关产品推荐

