2012-07-19 79 views
25

我注意到这个问题,当最近更新运行Ubuntu的计算机和Python的默认版本更改为2.7。为什么json.dumps(list(np.arange(5)))失败,而json.dumps(np.arange(5).tolist())工作

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 

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

+1

我看到一个类似的问题,我不能'json.dumps()'一个np.int64变量。但是,它适用于Python 2.7.9,但不适用于3.4。 – 2015-05-28 08:32:20

回答

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'> 

作为文档为tolist()说:

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

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

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

+0

你知道这是最近的变化吗?在系统升级之前用于工作的代码。 – azeey 2012-07-19 13:40:58

+0

不知道,我很害怕 - 甚至不知道如果改变是numpy(比如类型重命名)还是Python JSON方面(也许它用来更努力地处理未知类型?) – DSM 2012-07-19 14:57:01

+0

[简单解决方案] (http://stackoverflow.com/questions/8230315/python-sets-are-not-json-serializable)通过显式传递一个[默认处理程序](http://docs.python.org/2/library/json。 html#json.dumps)用于不可序列化的对象。 – 2013-08-22 05:41:22

24

因为与NumPy数组的元素不是本机整数,但numpy的自己的类型:

>>> type(np.arange(5)[0]) 
<type 'numpy.int64'> 

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

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)) 
1

问题是,第一个你没有得到一个int。你得到一个numpy.int64。这不能被序列化。