Python JSON编码器将NAN转换为null
我正在编写代码来接收能够转换为JSON的任意对象(可能是嵌套的) Python内置JSON编码器的默认行为是将NaN转换为Python JSON编码器将NAN转换为null,python,json,numpy,nan,Python,Json,Numpy,Nan,我正在编写代码来接收能够转换为JSON的任意对象(可能是嵌套的) Python内置JSON编码器的默认行为是将NaN转换为NaN,例如JSON.dumps(np.NaN)会导致NaN。如何将此NaN值更改为null 我试图做到以下几点: from json import JSONEncoder, dumps import numpy as np class NanConverter(JSONEncoder): def default(self, obj): tr
NaN
,例如JSON.dumps(np.NaN)
会导致NaN
。如何将此NaN
值更改为null
我试图做到以下几点:
from json import JSONEncoder, dumps
import numpy as np
class NanConverter(JSONEncoder):
def default(self, obj):
try:
_ = iter(obj)
except TypeError:
if isinstance(obj, float) and np.isnan(obj):
return "null"
return JSONEncoder.default(self, obj)
>>> d = {'a': 1, 'b': 2, 'c': 3, 'e': np.nan, 'f': [1, np.nan, 3]}
>>> dumps(d, cls=NanConverter)
'{"a": 1, "c": 3, "b": 2, "e": NaN, "f": [1, NaN, 3]}'
预期结果:
'{“a”:1,“c”:3,“b”:2,“e”:null,“f”:[1,null,3]}
不幸的是,您可能需要使用@Bramar的建议。你不能直接使用这个。对于Python的JSON编码器状态:
如果指定,则默认值是为无法序列化的对象调用的函数
您的
NanConverter.default
方法甚至没有被调用,因为Python的JSON编码器已经知道如何序列化np.nan
。添加一些打印语句-您将看到您的方法甚至没有被调用。这似乎实现了我的目标:
import simplejson
>>> simplejson.dumps(d, ignore_nan=True)
Out[3]: '{"a": 1, "c": 3, "b": 2, "e": null, "f": [1, null, 3]}'
转储(d,cls=NanConverter)
不幸地无法工作simplejson.dumps(d,ignore\u nan=True)
起作用,但引入了额外的依赖项(simplejson
)转储(pd.DataFrame(d).fillna(None))
,但请注意d.fillna(None)
将具有不可预测的行为:
请注意,fillna(None)
相当于fillna()
,这意味着value参数未使用。相反,它使用默认为正向填充的方法参数
数据帧。其中
:
df = pd.DataFrame(d)
dumps(df.where(pd.notnull(df), None)))
simplejson将在这里做正确的工作,但还有一个额外的标志值得包括: 尝试使用simplejson:
pip install simplejson
然后在代码中:
import simplejson
response = df.to_dict('records')
simplejson.dumps(response, ignore_nan=True,default=datetime.datetime.isoformat)
ignore_nan标志将正确处理所有nan-->空转换
默认标志将允许simplejson正确解析日期时间您可以使用simplejson但是如果您只想使用JSON模块,那么我的技巧是
json.dumps(d).replace(", NaN," , ', "null",')
对于使用Pandas的用户,最简单的方法是不需要第三方库:。这甚至可以转换嵌套结构中的NAN和其他Numpy类型:
df=pd.DataFrame({
“单词”:[“开”,“关”],
“列表”:[
[[1, 1, 1], [2, 2, 2], [3, 3, 3]],
[np.nan],[np.nan],[np.nan]],
“格言”:[
{'S':{'val':'A'}},
{'S':{'val':np.nan},
]
})
如果将其转换为DICT列表,Pandas将保留本机nan
值:
json.dumps(df.to_dict(orient='record'))
> [{
“词语”:“开”,
“列表”:[[1,1,1],[2,2,2],[3,3,3]],
“dicts”:{“S”:{“val”:“A”}
},
{
“单词”:“关”,
“列表”:[[NaN]、[NaN]、[NaN]],
“dicts”:{“S”:{“val”:NaN}
}]
但如果您直接将其转换为JSON字符串,它会为您解决:
df.to_json(orient='records')
> [{
“词语”:“开”,
“列表”:[[1,1,1]、[2,2,2]、[3,3,3],
“dicts”:{“S”:{“val”:“A”}
},
{
“单词”:“关”,
“列表”:[[null]、[null]、[null]],
“dicts”:{“S”:{“val”:null}
}]
请注意,
orient
值与to_dict()
和to_json()
之间略有不同,在Python json标准库中有一个可自定义的值,但尚未合并到中。我使用以下解决方法:
json_constant_map = {
'-Infinity': float('-Infinity'),
'Infinity': float('Infinity'),
'NaN': None,
}
def json_nan_to_none(obj: typing.Any, *, default: typing.Callable = None) -> None:
# We want to convert NaNs to None and we have to use for now this workaround.
# We still want an exception for infinity and -infinity.
# See: https://github.com/python/cpython/pull/13233
json_string = json.dumps(obj, default=default)
return json.loads(
json_string,
parse_constant=lambda constant: json_constant_map[constant],
)
为什么不在编码之前替换字典中的
NaN
s?我接收到一个可以转换为JSON的任意对象,而不是直接编码它。但是,我想确保在创建JSON字符串表示时,NaN被转换为null。我想这是否是JSON编码器中的一个错误,bec因为它生成的JSON无效。{“x”:NaN}在语法上不正确。它应该输出{“x”:“NaN”}或{“x”:null}。两者在语法上都是有效的-其中哪一个更有意义是另一个问题。有没有办法在内置json包中获得这种行为?我不希望对第三方包有另一种依赖性。这不是我能找到的。d
是一个字典。它没有where
方法。即使没有,它也没有似乎您的方法只返回非空值,而我希望null
位于值实际为空的位置。谢谢,我已更正了我的解决方案以适应dict。不确定您的其他备注;我必须考虑一下。此代码与OP的d
不兼容。即使您将此代码片段修复为使用d项s()
而不是d
,并从json
导入dumps
,列表中的nan
不会被转换。我建议您将关于默认值的解释作为注释添加到接受的答案中?似乎比用一个不相关的参数复制接受的答案更有意义t到OP的问题。它不应该是,null,
(不带引号)?另外,不用说,有许多可能的方法可以找到NaN(带和不带前导/扶手逗号,带/不带空格,作为数组的第一个或最后一个元素,等等)。