Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/342.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python JSON编码器将NAN转换为null_Python_Json_Numpy_Nan - Fatal编程技术网

Python JSON编码器将NAN转换为null

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

我正在编写代码来接收能够转换为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):
        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]}'
  • 正如@Gerrat所指出的,您的钩子
    转储(d,cls=NanConverter)
    不幸地无法工作

  • @Alexander的
    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(带和不带前导/扶手逗号,带/不带空格,作为数组的第一个或最后一个元素,等等)。