使用自定义python JSON编码器在字典中编码浮点数

时间:2017-11-14 01:17:02

标签: python json

这是一个简单的JSON编码器,可将浮点值转换为字符串:

class NestedEncoder(json.JSONEncoder):
    '''
    A JSON Encoder that converts floats/decimals to strings and allows nested objects
    '''

    def default(self, obj):

        if isinstance(obj, float) or obj.__class__.__name__ == "float32":
            return self.floattostr(obj)
        elif obj.__class__.__name__ == "type":
            return str(obj)
        elif hasattr(obj, 'repr_json'):
            return obj.repr_json()
        else:
            return json.JSONEncoder.default(self, obj)

    def floattostr(self,o,_inf=float('Inf'), _neginf=-float('-Inf'),nan_str="None"):
        if o != o:
            text = nan_str
        elif o == _inf:
            text = 'Infinity'
        elif o == _neginf:
            text = '-Infinity'
        else:
            return o.__repr__()

        return text

现在进行两项测试。第一个创建一个Infinity值float,并使用自定义编码器对其进行编码。测试通过。

def test_inf():
    inf = float('Inf')
    as_json = json.dumps(inf,cls=NestedEncoder)
    assert as_json == "Infinity"

第二个测试做同样的事情,但将浮点数放在字典中:

def test_inf_dic():
    inf = float('Inf')
    as_json = json.dumps({'key':inf},cls=NestedEncoder)
    assert as_json == "{'key':'Infinity'}"

输出:

=================================== FAILURES ===================================
_________________________________ test_inf_dic _________________________________

    def test_inf_dic():
        inf = float('Inf')
        as_json = json.dumps({'key':inf},cls=NestedEncoder)
>       assert as_json == "{'key':'Infinity'}"
E       assert '{"key": Infinity}' == "{'key':'Infinity'}"
E         - {"key": Infinity}
E         ?  ^   ^ ^
E         + {'key':'Infinity'}
E         ?  ^   ^ ^        +

编辑:

自定义编码器仅在第一次测试时被调用,而不是第二次测试。

1 个答案:

答案 0 :(得分:0)

您的测试期间未调用自定义函数,这是正确的。其原因在文档中解释:

  

如果指定,则default应该是为无法以其他方式序列化的对象调用的函数。它应该返回对象的JSON可编码版本或引发TypeError。如果未指定,则引发TypeError。

由于float是一个已经知道如何序列化的对象,因此不会调用它。对于float序列化,您可以覆盖encode函数。