如何在Pydantic V2中实现JSON序列化时按键排序?
我完全懂你碰到的这个问题!在Pydantic V1里,我们可以通过dumps_kwargs把sort_keys这类参数直接传给底层的json.dumps,但升级到V2之后,原来的obj.json(sort_keys=True)写法直接报错TypeError: 'dumps_kwargs' keyword arguments are no longer supported,确实挺闹心的。而且你提到的用model_dump()配合json.dumps的临时方案,只对简单类型有效,遇到Pydantic能处理的复杂类型(比如datetime、UUID、嵌套模型这类)就失效了。
不过别担心,这里有几个通用的解决方法,既能实现按键排序,又能保留Pydantic对复杂类型的序列化能力:
方法一:单次序列化时直接配置(最灵活)
我们可以借助Pydantic内置的pydantic_encoder来处理复杂类型,同时给json.dumps传入sort_keys=True参数:
import json from pydantic import BaseModel from pydantic.json import pydantic_encoder class JsonTest(BaseModel): b_field: int a_field: str obj = JsonTest(b_field=1, a_field="one") # 支持所有Pydantic可序列化类型的按键排序写法 serialized_json = json.dumps( obj.model_dump(), sort_keys=True, default=pydantic_encoder ) print(serialized_json) # 输出结果:{"a_field": "one", "b_field": 1}
这里的default=pydantic_encoder会让json.dumps调用Pydantic的专属编码器,处理它能识别的所有复杂类型,同时sort_keys=True保证输出的JSON按键排序。
方法二:封装成模型基类(适合多模型复用)
如果你的项目里多个模型都需要按键排序的序列化功能,可以封装一个基类,把排序逻辑统一实现:
import json from pydantic import BaseModel from pydantic.json import pydantic_encoder class BaseSortedModel(BaseModel): def model_dump_json_sorted(self): """带按键排序的JSON序列化方法""" return json.dumps( self.model_dump(), sort_keys=True, default=pydantic_encoder ) # 继承基类使用 class JsonTest(BaseSortedModel): b_field: int a_field: str obj = JsonTest(b_field=1, a_field="one") print(obj.model_dump_json_sorted()) # 输出结果:{"a_field": "one", "b_field": 1}
这样所有继承BaseSortedModel的子类,都可以直接调用model_dump_json_sorted()来获取有序的JSON字符串。
补充说明
Pydantic V2移除dumps_kwargs是为了让序列化逻辑更清晰,把底层json.dumps的参数控制交给用户自己处理,配合内置的pydantic_encoder就能完美替代原来的功能,而且灵活性更高。
备注:内容来源于stack exchange,提问作者mmdanziger

