0

0

Pydantic model_dump 忽略 extra 字段的优雅实现

DDD

DDD

发布时间:2025-09-07 11:19:01

|

809人浏览过

|

来源于php中文网

原创

Pydantic model_dump 忽略 extra 字段的优雅实现

本文介绍了一种在 Pydantic 模型序列化时,优雅地排除未定义额外字段的通用方法。通过创建自定义基类并利用 model_serializer 的 wrap 模式,我们可以确保 model_dump 的输出仅包含模型中明确定义的字段,从而避免在处理带有 ConfigDict(extra='allow') 的复杂嵌套模型时,出现不必要的额外数据。这种方法提供了一种简洁且可复用的解决方案,以实现更严格的数据输出控制。

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 排除额外字段

核心思想是创建一个名为 MyBaseModel 的基类,所有需要此功能的 Pydantic 模型都将继承自它。在这个基类中,我们定义一个包装序列化器,它会在 Pydantic 完成默认的序列化后,对结果字典进行过滤,只保留那些在模型中明确定义的字段。

MyMap AI
MyMap AI

使用AI将想法转化为图表

下载
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("断言成功:定义的字段正常保留。")

代码解析

  1. MyBaseModel(BaseModel): 我们创建了一个新的基类 MyBaseModel,它继承自 Pydantic 的 BaseModel。
  2. @model_serializer(mode="wrap"): 这是 Pydantic V2 引入的一个强大特性。
    • model_serializer 装饰器允许我们为模型定义自定义的序列化逻辑。
    • mode="wrap" 指定了序列化器的工作模式为“包装”。这意味着我们的 _serialize 方法将接收一个 handler 函数作为参数。这个 handler 函数会执行 Pydantic 默认的序列化逻辑,并返回一个字典。我们的包装器可以在此基础上对结果进行修改。
  3. _serialize(self, handler: SerializerFunctionWrapHandler) -> dict[str, Any]:
    • self: 当前模型实例。
    • handler: 一个可调用对象,调用 handler(self) 会返回模型实例的默认序列化字典表示。
  4. default_dumped_data = handler(self): 这一步是关键。它首先让 Pydantic 完成其常规的序列化过程,生成一个包含所有字段(包括额外字段,如果 extra="allow")的字典。
  5. filtered_data = {k: v for k, v in default_dumped_data.items() if k in self.model_fields}:
    • self.model_fields: 这是 Pydantic 模型的一个内部属性,它是一个字典,包含了模型中所有明确定义字段的名称(作为键)和它们的 FieldInfo 对象(作为值)。通过检查 k in self.model_fields,我们可以确定一个键是否是模型中定义的合法字段。
    • 这个字典推导式遍历 default_dumped_data 中的所有键值对,只保留那些键存在于 self.model_fields 中的项。这样,所有未在模型中定义的额外字段都会被过滤掉。
  6. return filtered_data: 返回经过过滤后的字典,作为 model_dump() 的最终结果。

注意事项与最佳实践

  • 继承关系: 确保所有需要排除额外字段的模型都直接或间接继承自 MyBaseModel。
  • Pydantic V2 特性: model_serializer 是 Pydantic V2 的特性。如果您使用的是 Pydantic V1,需要采用不同的方法(例如重写 json() 或 dict() 方法,但实现会更复杂)。
  • 性能考量: 这种方法在默认序列化之后增加了一次字典遍历和过滤操作。对于大多数应用而言,这种开销可以忽略不计。但在处理极其庞大或序列化频率极高的模型时,需要评估其对性能的潜在影响。
  • 通用性: 这种方法是通用的,它会作用于所有继承 MyBaseModel 的模型实例,无论它们是根模型还是嵌套模型,都能确保其 model_dump 输出不包含额外字段。
  • 与 exclude 参数的区别: model_dump 的 exclude 参数用于排除模型中 已定义 的特定字段。而我们这里的解决方案是排除模型中 未定义 的所有额外字段,两者目的不同,可以结合使用。

通过这种定制化的 MyBaseModel 方案,我们为 Pydantic 模型提供了一种优雅、可复用且强大的机制,以确保在序列化输出中严格控制数据内容,只包含模型架构中明确定义的字段,从而提升数据输出的清晰度和一致性。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
json数据格式
json数据格式

JSON是一种轻量级的数据交换格式。本专题为大家带来json数据格式相关文章,帮助大家解决问题。

420

2023.08.07

json是什么
json是什么

JSON是一种轻量级的数据交换格式,具有简洁、易读、跨平台和语言的特点,JSON数据是通过键值对的方式进行组织,其中键是字符串,值可以是字符串、数值、布尔值、数组、对象或者null,在Web开发、数据交换和配置文件等方面得到广泛应用。本专题为大家提供json相关的文章、下载、课程内容,供大家免费下载体验。

536

2023.08.23

jquery怎么操作json
jquery怎么操作json

操作的方法有:1、“$.parseJSON(jsonString)”2、“$.getJSON(url, data, success)”;3、“$.each(obj, callback)”;4、“$.ajax()”。更多jquery怎么操作json的详细内容,可以访问本专题下面的文章。

313

2023.10.13

go语言处理json数据方法
go语言处理json数据方法

本专题整合了go语言中处理json数据方法,阅读专题下面的文章了解更多详细内容。

77

2025.09.10

if什么意思
if什么意思

if的意思是“如果”的条件。它是一个用于引导条件语句的关键词,用于根据特定条件的真假情况来执行不同的代码块。本专题提供if什么意思的相关文章,供大家免费阅读。

783

2023.08.22

2026赚钱平台入口大全
2026赚钱平台入口大全

2026年最新赚钱平台入口汇总,涵盖任务众包、内容创作、电商运营、技能变现等多类正规渠道,助你轻松开启副业增收之路。阅读专题下面的文章了解更多详细内容。

31

2026.01.31

高干文在线阅读网站大全
高干文在线阅读网站大全

汇集热门1v1高干文免费阅读资源,涵盖都市言情、京味大院、军旅高干等经典题材,情节紧凑、人物鲜明。阅读专题下面的文章了解更多详细内容。

20

2026.01.31

无需付费的漫画app大全
无需付费的漫画app大全

想找真正免费又无套路的漫画App?本合集精选多款永久免费、资源丰富、无广告干扰的优质漫画应用,涵盖国漫、日漫、韩漫及经典老番,满足各类阅读需求。阅读专题下面的文章了解更多详细内容。

28

2026.01.31

漫画免费在线观看地址大全
漫画免费在线观看地址大全

想找免费又资源丰富的漫画网站?本合集精选2025-2026年热门平台,涵盖国漫、日漫、韩漫等多类型作品,支持高清流畅阅读与离线缓存。阅读专题下面的文章了解更多详细内容。

4

2026.01.31

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
最新Python教程 从入门到精通
最新Python教程 从入门到精通

共4课时 | 22.4万人学习

Django 教程
Django 教程

共28课时 | 3.7万人学习

SciPy 教程
SciPy 教程

共10课时 | 1.3万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号