如何配置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
相关产品推荐
相关产品推荐

