Почему json.dumps(list (np.arange(5))) сбой, тогда как json.dumps(np.arange(5).tolist()) работает
Я заметил эту проблему, когда недавно был обновлен компьютер с 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
Есть ли разница между list() и tolist() metd массива numpy?
Ответы
Ответ 1
Похоже, что метод 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.
Последняя строка имеет здесь значение.
Ответ 2
Поскольку элементы массива NumPy не являются родными ints, а являются собственными типами NUmPy:
>>> type(np.arange(5)[0])
<type 'numpy.int64'>
Вы можете использовать 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))
Ответ 3
Проблема в том, что с первой вы не получите int. Вы получаете numpy.int64. Это не может быть сериализовано.