¿Por qué falla json.dumps (list (np.arange (5))) mientras json.dumps (np.arange (5) .tolist ()) funciona?

Noté este problema cuando una computadora que ejecuta Ubuntu se actualizó recientemente y la versión predeterminada de Python cambió a 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 

¿Hay alguna diferencia entre list () y el método tolist () de una matriz numpy?

Parece que el método tolist() convierte el número int32 (o cualquier tamaño que tengas) de nuevo en un int , con lo que JSON sabe qué hacer:

 >>> list(np.arange(5)) [0, 1, 2, 3, 4] >>> type(list(np.arange(5)))  >>> type(list(np.arange(5))[0])  >>> np.arange(5).tolist() [0, 1, 2, 3, 4] >>> type(np.arange(5).tolist())  >>> type(np.arange(5).tolist()[0])  

Como dicen los documentos para tolist() :

Devuelve la matriz como una lista (posiblemente anidada).

Devuelva una copia de los datos de la matriz como una lista de Python (anidada). Los elementos de datos se convierten al tipo de Python compatible más cercano.

La última línea hace la diferencia aquí.

Debido a que los elementos de una matriz NumPy no son entradas nativas, sino de los tipos propios de NUmPy:

 >>> type(np.arange(5)[0])  

Puede usar un JSONEncoder personalizado para admitir el tipo ndarray devuelto por 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)) 

El problema es que con el primero no obtienes un int. Obtienes un numpy.int64. Eso no puede ser serializado.