You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在自定义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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 15:15:36