Pydantic 2:JSON 将集合序列化为排序列表

问题描述 投票:0回答:1
背景

在 Pydantic 2 中,

set

 类型的字段已经 JSON 序列化为列表。然而,这些列表是无序的。或者,更具体地说,他们的项目是根据原始集合的内部排序进行排序的。

不幸的是,即使两个集合包含相同的项目,它们的内部顺序可能仍然不同。因此,在没有显式排序的情况下序列化集合会产生不确定的结果。

问题

我正在寻找一种方法来配置特定的 Pydantic 2 模型,以将其类型为

set

 的所有字段首先 JSON 序列化为排序列表,然后再将结果转换为字符串。我想避免定义自定义设置类型或为每个此类属性添加自定义类型注释。该解决方案应该更通用,因为可能需要这种处理的属性数量更大。此外,它们也可能在该特定模型的子类中定义。

有没有一种相当简单的方法来实现这一目标?

选项

在我看来,使用

模型序列化器是最直接的方法。但同时,对我来说,循环遍历所有属性、检查它们的类型、调用项目的序列化例程然后将结果排序到列表中似乎很麻烦。如果可能的话,我想避免这种情况,并以某种方式利用 Pydantic 关于属性类型的知识。

在 Pydantic 1 中,可以通过使用配置的

json_encoders

 参数并为 set
 类型的所有属性定义自定义序列化函数来实现所需的效果。然而,在 Pydantic 2 中,由于“性能开销和实现复杂性”,该选项已被“删除”。好像可以理解。
我不一定要寻找一种模仿 Pydantic 1 行为的方法。如果有一种方法可以使用主要或推荐的 Pydantic 2 功能实现类似的效果,我更愿意使用它。

似乎在 JSON 序列化的某个时刻,Pydantic 无论如何都会将集合转换为列表。在理想情况下,我想以某种方式利用这种转换,并仅就其结果调用

sorted


python serialization pydantic
1个回答
0
投票
序列化为排序列表 pydantic 2 (准确地说是 2.6)可以使用

@field_serializer

 装饰器来完成。 
来源:pydantic 文档 > 函数序列化器

这是参考文档中给出的示例:

from typing import Set from pydantic import BaseModel, field_serializer class StudentModel(BaseModel): name: str = 'Jane' courses: Set[str] @field_serializer('courses', when_used='json') def serialize_courses_in_order(courses: Set[str]): return sorted(courses) student = StudentModel(courses={'Math', 'Chemistry', 'English'}) print(student.model_dump_json()) #> {"name":"Jane","courses":["Chemistry","English","Math"]}

属性
courses
被序列化为排序列表。

您还可以一次提供多个属性:

class AnotherModel(BaseModel): a: Set[str] b: Set[str] @field_serializer('a', 'b', when_used='json') def serialize_sets(set_of_str: Set[str]): return sorted(set_of_str)

(我认为要概述 pydantic 的众多功能并不是一件容易的事。我花了一些时间才发现这一点😉)
    

© www.soinside.com 2019 - 2024. All rights reserved.