Python自定义JSON编码器无法处理numpy NaN或Infinite值

时间:2018-07-31 10:14:25

标签: python json numpy python-3.6

因此,我正在尝试编写一个自定义编码器,以处理不同的jar值:

ooxml-lib

但是,它似乎没有处理numpyclass NumpyEncoder(DjangoJSONEncoder): def default(self, obj): if isinstance(obj, np.integer): return int(obj) elif isinstance(obj, np.floating): return float(obj) elif isinstance(obj, np.ndarray): return obj.tolist() if np.isnan(obj) or np.isinf(obj): return None else: return super().default(obj) 对象:

np.NaN

我也尝试过使用np.inf,但这也不起作用。

我想要将obj = {'test': np.NaN, 'test2': np.inf} json.dumps(obj, cls=LazyNumpyEncoder) Out[5]: '{"test": NaN, "test2": Infinity}' 和Infinite(包括负的无限值)转换为空值。

有人知道我哪里出问题了吗?

2 个答案:

答案 0 :(得分:1)

这里的原因是$userData = $request->validate([ 'email' => 'required|string|email|max:255|unique:users', 'number_of_whatever' => 'nullable' ]); 方法只能用于使 new 类型可序列化。它不能用于覆盖default中已经定义的类型的序列化。 json的文档字符串说的是(强调我的):

  

要将其扩展为识别其他对象,请使用其他方法子类化并实现JSONEncoder方法,并在可能的情况下为.default()返回可序列化的对象,否则应调用超类实现(引发o)。

如果查看源代码,您会注意到在所有其他序列化尝试均失败之后,将调用TypeError。因此,OP帖子中的代码不会被调用。根据以上引用,default实现了DjangoJSONEncoder以使其了解日期/时间,十进制类型和UUID。

关于如何解决此问题的方法-好吧,我不会理会子类化,而是递归地处理dict(请注意循环!),并在将dict传递到{{之前,用default替换NaN和Infs。 1}}。也可以使用None来确保在调用转储之前捕获了所有NaN。

另一个选择-子类json.dumps / json.dumps(..., allow_nan=False),覆盖JSONEncoder,插入上述算法,并将其余工作传递给父类。

答案 1 :(得分:1)

所以@Vovanrock很好地解释了它,但我将发布解决该问题的方法。在通过dumps运行字典之前,我只是将infnan对象转换为字符串:

def _convert_numpy_objects(self, dict_to_convert : Dict) -> Dict:
    new = {}
    for k, v in dict_to_convert.items():
        if isinstance(v, dict):
            new[k] = self._convert_numpy_objects(v)
        else:
            if isinstance(v, float) and (np.isnan(v) or np.isinf(v)):
                new[k] = str(v)
            else:
                new[k] = v
    return new