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

如何在Pydantic v2中导出部分含None值的字段?

Pydantic v2 实现部分None字段强制导出的问题

我有一个包含多个可设为None值字段的Pydantic v2模型,Pydantic提供两种模型导出的便捷操作:

  • 调用model_dump时,通过include参数指定仅导出特定字段;
  • 设置exclude_none=True,自动排除值为None的字段。

我需要实现的需求是:部分字段即使值为None也要强制导出,其余None字段则排除。但同时使用include和exclude_none参数时,exclude_none优先级更高,导致预期结果无法实现。比如下面的单元测试会失败:

import unittest
from pydantic import BaseModel

class A(BaseModel):
    a: str | None

class PydanticIncludeAndExcludedNoneTestCase(unittest.TestCase):
    """展示在导出Pydantic v2模型时,`exclude_none`优先级高于`include`"""
    def test_simple(self):
        item = A(a=None)
        d = item.model_dump(include={'a'}, exclude_none=True)
        self.assertEqual(d['a'], None)  # 断言失败,因为d中没有'a'字段

if __name__ == '__main__':
    unittest.main()

解决方案1:自定义模型的导出方法

通过给需要强制导出的字段添加自定义标记,然后编写自定义导出方法,先执行exclude_none过滤,再把标记过的字段强制加回去:

from pydantic import BaseModel, Field

class A(BaseModel):
    # 给需要强制导出的字段添加自定义标记
    a: str | None = Field(..., serialization_always_include=True)
    b: str | None
    c: str = "default"

    def custom_dump(self, always_include_fields: set[str] | None = None):
        # 先导出所有非None字段
        base_dump = self.model_dump(exclude_none=True)
        # 自动识别带标记的字段,或者使用传入的字段集合
        target_fields = always_include_fields or {
            k for k, v in self.model_fields.items() 
            if v.field_info.extra.get('serialization_always_include')
        }
        # 将目标字段的当前值加入结果,覆盖可能的缺失
        for field in target_fields:
            if field in self.model_fields:
                base_dump[field] = getattr(self, field)
        return base_dump

对应的测试用例:

import unittest

class TestCustomDump(unittest.TestCase):
    def test_partial_include_none(self):
        item = A(a=None, b=None)
        result = item.custom_dump()
        self.assertEqual(result, {'a': None, 'c': 'default'})

if __name__ == '__main__':
    unittest.main()

解决方案2:手动合并导出结果

如果不想修改模型结构,可以手动执行两次导出后合并结果,优先保留需要强制导出的字段:

item = A(a=None, b=None, c="test")
# 第一步:导出需要强制包含的字段(即使值为None)
included_fields = item.model_dump(include={'a', 'c'})
# 第二步:导出所有非None字段
excluded_none_fields = item.model_dump(exclude_none=True)
# 合并结果,优先保留强制包含的字段
final_result = {**excluded_none_fields, **included_fields}
# final_result 结果为 {'a': None, 'c': 'test'}

原因说明

Pydantic v2的model_dump执行逻辑是先应用exclude_none过滤所有None值字段,再执行include/exclude的字段筛选,所以即使你用include指定了某个字段,如果它的值是None且开启了exclude_none=True,最终还是会被过滤掉。

内容的提问来源于stack exchange,提问作者Michael

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 01:52:50