如何在自定义Thing类中配置Pydantic的JSON编码器?
问题描述
我定义了如下自定义Thing类:
class Thing: def __init__(self, x: str): self.x = x def __str__(self): return self.x @classmethod def __get_validators__(cls): yield cls.validate @classmethod def validate(cls, v: str) -> "Thing": return cls(v)
通过验证器方法,我可以将该类作为Pydantic模型的自定义字段类型使用:
from pydantic import BaseModel from thing import Thing class Model(BaseModel): thing: Thing
但要序列化为JSON时,我需要在Pydantic模型中设置json_encoders选项:
class Model(BaseModel): class Config: json_encoders = { Thing: str } thing: Thing
现在Pydantic可以完成Thing类的JSON序列化与反序列化,但配置分散在Model和Thing两处。我希望将所有配置集中在Thing类上,请问是否有办法在Thing类中设置json_encoders,让Pydantic能自动处理?
注:此处Thing类是简化版,实际包含大量逻辑,并非仅自定义str类型。
解决方案
可以通过以下几种方式将序列化配置完全封装到Thing类内部,避免在模型中重复配置:
方法1:实现__json_encoder__类方法
Pydantic会自动识别自定义类型中的__json_encoder__类方法,将其作为该类型的默认JSON编码器。在Thing类中添加这个方法即可:
class Thing: def __init__(self, x: str): self.x = x def __str__(self): return self.x @classmethod def __get_validators__(cls): yield cls.validate @classmethod def validate(cls, v: str) -> "Thing": return cls(v) @classmethod def __json_encoder__(cls, obj): # 这里编写实际的序列化逻辑,示例用str转换 return str(obj)
之后在模型中直接使用Thing类型,无需额外配置json_encoders:
class Model(BaseModel): thing: Thing
方法2:实现dict()方法(适用于复杂结构序列化)
如果Thing需要序列化为多字段的JSON对象,可以在类中定义dict()方法,Pydantic会自动调用该方法生成序列化结果:
class Thing: def __init__(self, x: str, y: int): self.x = x self.y = y def __str__(self): return self.x @classmethod def __get_validators__(cls): yield cls.validate @classmethod def validate(cls, v): # 根据实际需求编写验证逻辑 if isinstance(v, dict): return cls(v['x'], v['y']) return cls(v, 0) def dict(self): return {"x": self.x, "y": self.y}
使用时模型无需任何额外配置,Pydantic会自动处理序列化。
方法3:让Thing继承BaseModel
如果场景允许,直接让Thing继承Pydantic的BaseModel,这样序列化、反序列化及验证逻辑都可以封装在类内部:
from pydantic import BaseModel, field_validator class Thing(BaseModel): x: str @field_validator('x') def validate_x(cls, v): # 自定义字段验证逻辑 if len(v) < 3: raise ValueError("x长度不能小于3") return v # 自定义序列化规则可以通过model_config配置 model_config = { "json_encoders": {str: lambda s: s.upper()} }
这种方式下Thing本身就是一个Pydantic模型,作为其他模型的字段时,无需额外配置即可完成序列化和反序列化。
内容的提问来源于stack exchange,提问作者2e0byo
相关产品推荐
相关产品推荐

