为什么json.dumps(list(np.arange(5)))失败而json.dumps(np.arange(5).tolist())有效

aze*_*eey 26 python numpy python-2.7

当最近更新运行Ubuntu的计算机并且Python的默认版本更改为2.7时,我注意到了这个问题.

import json
import numpy as np

json.dumps(list(np.arange(5))) # Fails, throws a "TypeError: 0 is not JSON serializable"
json.dumps(np.arange(5).tolist()) # Works 
Run Code Online (Sandbox Code Playgroud)

list()和numpy数组的tolist()方法有区别吗?

phi*_*hag 24

因为NumPy数组的元素不是本机int,而是NUmPy自己的类型:

>>> type(np.arange(5)[0])
<type 'numpy.int64'>
Run Code Online (Sandbox Code Playgroud)

您可以使用自定义JSONEncoder来支持ndarray返回的类型arange:

import numpy as np
import json

class NumPyArangeEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, np.ndarray):
            return obj.tolist() # or map(int, obj)
        return json.JSONEncoder.default(self, obj)

print(json.dumps(np.arange(5), cls=NumPyArangeEncoder))
Run Code Online (Sandbox Code Playgroud)


DSM*_*DSM 23

看起来这个tolist()方法将numpy int32(或你拥有的任何大小)变回一个int,JSON知道如何处理:

>>> list(np.arange(5))
[0, 1, 2, 3, 4]
>>> type(list(np.arange(5)))
<type 'list'>
>>> type(list(np.arange(5))[0])
<type 'numpy.int32'>
>>> np.arange(5).tolist()
[0, 1, 2, 3, 4]
>>> type(np.arange(5).tolist())
<type 'list'>
>>> type(np.arange(5).tolist()[0])
<type 'int'>
Run Code Online (Sandbox Code Playgroud)

正如文档所说tolist():

将数组作为(可能是嵌套的)列表返回.

将数组数据的副本作为(嵌套)Python列表返回.数据项将转换为最接近的兼容Python类型.

最后一行在这里有所不同.