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

如何配置Pydantic的model_dump()方法将nan转换为None返回

如何配置Pydantic的model_dump()方法将nan转换为None返回

嘿,这个问题我之前也碰到过!要让Pydantic的model_dump()把浮点型的nan转换成None返回,有两种实用的方法,你可以根据自己的需求来选:

方案一:在数据校验阶段就替换nan为None

这种方法会在数据被模型解析时就把nan换成None,模型内部存储的就是None,后续调用model_dump()直接就能得到想要的结果。

你可以给模型添加一个字段验证器(field_validator),指定mode='before'来在数据进入模型前处理:

from pydantic import BaseModel, field_validator
import math

class FooClass(BaseModel):
    foo: list[float | None]  # 这里要把类型改成允许None

    @field_validator('foo', mode='before')
    def replace_nan_with_none(cls, value):
        # 遍历列表,把每个nan替换成None
        return [None if isinstance(item, float) and math.isnan(item) else item for item in value]

# 测试你的代码
invalid_data = {
    "foo": [250.5, 251.0, float("nan")]
}
data = FooClass(**invalid_data)
dict_data = data.model_dump()
assert dict_data["foo"] == [250.5, 251.0, None]  # 现在这个断言就能通过啦

方案二:序列化时临时转换nan为None

如果不想修改模型内部存储的数据(比如还需要保留nan用于其他逻辑),只在调用model_dump()的时候转换,那可以用自定义编码器:

方式1:调用model_dump时传入custom_encoder

from pydantic import BaseModel
import math

class FooClass(BaseModel):
    foo: list[float]  # 这里类型还是float,不需要改

invalid_data = {
    "foo": [250.5, 251.0, float("nan")]
}
data = FooClass(**invalid_data)

# 定义一个处理列表的编码器
def nan_to_none_list_encoder(obj):
    return [None if isinstance(item, float) and math.isnan(item) else item for item in obj]

# 调用model_dump时指定自定义编码器
dict_data = data.model_dump(custom_encoder={list: nan_to_none_list_encoder})
assert dict_data["foo"] == [250.5, 251.0, None]

方式2:全局配置模型的json_encoders

如果你的模型有很多嵌套结构(比如字典、子模型),想全局处理所有nan,可以在模型配置里加一个递归处理的编码器:

from pydantic import BaseModel
import math
from typing import Any

# 递归处理所有类型里的nan
def handle_all_nan(obj: Any) -> Any:
    if isinstance(obj, float) and math.isnan(obj):
        return None
    elif isinstance(obj, list):
        return [handle_all_nan(item) for item in obj]
    elif isinstance(obj, dict):
        return {key: handle_all_nan(value) for key, value in obj.items()}
    # 如果是其他类型(比如子模型),直接返回原对象
    return obj

class FooClass(BaseModel):
    foo: list[float]

    model_config = {
        "json_encoders": {
            list: handle_all_nan,
            float: lambda x: None if math.isnan(x) else x
        }
    }

# 测试
invalid_data = {
    "foo": [250.5, 251.0, float("nan")]
}
data = FooClass(**invalid_data)
dict_data = data.model_dump()
assert dict_data["foo"] == [250.5, 251.0, None]

小提示

  • 方案一适合需要模型内部就存储None的场景,记得要把字段类型改成允许None(比如list[float | None]);
  • 方案二适合只在序列化时转换,不改变模型内部数据的场景;
  • 你的环境是Pydantic 2.7.x,这些方法都能正常工作哦~

备注:内容来源于stack exchange,提问作者EUDES FILHO

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.14 11:53:02