
pydantic 作为一款强大的数据验证和序列化库,在现代python应用开发中扮演着核心角色。然而,在处理某些特定场景时,我们可能会遇到一个常见的需求:当模型配置允许额外字段(configdict(extra="allow"))时,model_dump() 方法会将这些未在模型中明确定义的额外数据也包含在序列化输出中。尽管 model_dump 提供了 exclude 等参数用于排除特定字段,但并没有直接的 exclude_extras 选项来一劳永逸地排除所有额外字段,尤其是在面对复杂的多层嵌套模型时,手动迭代和清理输出会变得异常繁琐且容易出错。
例如,考虑以下Pydantic模型定义:
from pydantic import BaseModel, ConfigDict
class Nested(BaseModel):
model_config = ConfigDict(extra="allow")
baz: str
class Root(BaseModel):
foo: int = 10
bar: int
nested: Nested
# 当创建模型实例时,nested 字典中包含了一个未定义的 "extra" 字段
model = Root(foo=10, bar=20, nested={"baz": "boing", "extra": "so special"})
# 默认的 model_dump 会包含这个 "extra" 字段
dumped_data = model.model_dump()
# dumped_data['nested'] 会是 {'baz': 'boing', 'extra': 'so special'}
# 我们的目标是让 assert "extra" not in dumped_data["nested"] 成立在这种情况下,我们期望 model_dump() 的结果中不包含 nested 字典中的 "extra" 字段。为了实现这一目标,我们可以利用 Pydantic V2 提供的 model_serializer 装饰器,结合 wrap 模式,创建一个自定义的基类来统一处理所有模型的序列化行为。
核心思想是创建一个名为 MyBaseModel 的基类,所有需要此功能的 Pydantic 模型都将继承自它。在这个基类中,我们定义一个包装序列化器,它会在 Pydantic 完成默认的序列化后,对结果字典进行过滤,只保留那些在模型中明确定义的字段。
from typing import Any
from pydantic import BaseModel, ConfigDict, model_serializer, SerializerFunctionWrapHandler, FieldSerializationInfo
class MyBaseModel(BaseModel):
"""
一个自定义的Pydantic基类,用于在序列化时自动排除未定义的额外字段。
"""
@model_serializer(mode="wrap")
def _serialize(self, handler: SerializerFunctionWrapHandler) -> dict[str, Any]:
"""
包装序列化器,在默认序列化结果的基础上过滤掉额外字段。
:param handler: Pydantic提供的默认序列化处理器。
:return: 经过过滤后的字典表示。
"""
# 调用handler(self)获取Pydantic默认的序列化结果
default_dumped_data = handler(self)
# 使用字典推导式过滤结果,只保留模型中实际定义的字段
# self.model_fields 包含了所有明确定义的字段名称
filtered_data = {
k: v for k, v in default_dumped_data.items()
if k in self.model_fields
}
return filtered_data
class Nested(MyBaseModel):
"""
一个嵌套模型,允许额外字段,但序列化时会排除它们。
"""
model_config = ConfigDict(extra="allow")
baz: str
class Root(MyBaseModel):
"""
根模型,包含嵌套模型,序列化时会排除所有层级的额外字段。
"""
foo: int = 10
bar: int
nested: Nested
if __name__ == "__main__":
# 创建包含额外字段的模型实例
model = Root(foo=10, bar=20, nested={"baz": "boing", "extra": "so special"})
# 调用 model_dump 进行序列化
dumped_data = model.model_dump()
print(f"原始模型实例: {model}")
print(f"序列化后的数据: {dumped_data}")
# 验证 "extra" 字段是否已被排除
assert "extra" not in dumped_data["nested"]
print("断言成功:'extra' 字段已从嵌套模型中排除。")
# 验证其他字段是否正常保留
assert dumped_data["foo"] == 10
assert dumped_data["bar"] == 20
assert dumped_data["nested"]["baz"] == "boing"
print("断言成功:定义的字段正常保留。")通过这种定制化的 MyBaseModel 方案,我们为 Pydantic 模型提供了一种优雅、可复用且强大的机制,以确保在序列化输出中严格控制数据内容,只包含模型架构中明确定义的字段,从而提升数据输出的清晰度和一致性。
以上就是Pydantic model_dump 忽略 extra 字段的优雅实现的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号