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

如何在Pydantic 2中将set类型字段序列化为有序列表?

问题背景

在Pydantic 2中,set类型字段会被JSON序列化为列表,但这些列表的顺序依赖集合内部的排序规则,是无序且不确定的——即使两个集合包含完全相同的元素,序列化后的列表顺序也可能不同。

需求

希望为某个Pydantic 2模型配置全局规则,将其所有set类型字段先序列化为有序列表,再完成后续序列化。要求避免定义自定义set类型,也不为每个set属性单独添加自定义注解(需处理的属性数量多,且可能存在于模型的子类中)。

可选思路分析
  • 原本考虑用模型序列化器,但需要手动遍历所有属性、检查类型、调用元素序列化逻辑再排序,操作繁琐,希望能复用Pydantic对字段类型的内置判断来简化流程。
  • Pydantic 1中可以通过json_encoders配置全局处理set类型,但Pydantic 2已移除该功能(官方出于性能和实现复杂度考量),因此倾向于使用Pydantic 2的原生特性实现。理想状态是在Pydantic将集合转换为列表的环节介入,仅对结果调用sorted()方法。
解决方案

可以通过全局字段序列化器实现,在父模型中定义一个通用的序列化逻辑,自动匹配所有set类型字段并排序,子类继承后即可自动生效:

from pydantic import BaseModel, field_serializer
from typing import Set, Any

class BaseSortedSetModel(BaseModel):
    @field_serializer('*', when_used='always')
    def handle_sets(self, value: Any, info) -> Any:
        # 判断当前字段是否为set类型(兼容泛型Set[T])
        annotation = info.field.annotation
        if (hasattr(annotation, '__origin__') 
            and annotation.__origin__ is set):
            return sorted(value)
        # 非set类型字段沿用默认序列化逻辑
        return value

# 测试示例子类
class UserTags(BaseSortedSetModel):
    name: str
    tags: Set[str]
    scores: Set[int]

# 验证效果
user = UserTags(name="Alice", tags={"python", "pydantic", "dev"}, scores={90, 80, 95})
print(user.model_dump_json(indent=2))

代码说明

  1. @field_serializer('*', when_used='always'):*表示匹配模型所有字段,when_used='always'确保无论字段是否为默认值都会触发该序列化逻辑。
  2. 类型判断:通过info.field.annotation获取字段的注解类型,检查其__origin__是否为set,兼容Set[str]、Set[int]等泛型集合类型。
  3. 排序处理:对set类型的字段值调用sorted(),将无序集合转换为有序列表,其他字段沿用Pydantic默认序列化逻辑。

优势

  • 无需自定义set类型或逐个字段添加注解,一次配置即可覆盖父模型及所有子类的set字段。
  • 完全复用Pydantic的原生序列化流程,仅在必要环节介入排序,性能开销低。

内容的提问来源于stack exchange,提问作者Peter Bašista

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 02:13:16