¿Por qué json.volcados (lista (np.arange (5))) falla mientras json.vertederos(np.arange (5).tolist()) obras


Noté este problema cuando un equipo 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 una diferencia entre list() y el metd de tolist() de un array numpy?

Author: azeey, 2012-07-19

3 answers

Parece que el método tolist() convierte el numpy int32 (o cualquier tamaño que tengas) en un int, con el que JSON sabe qué hacer:

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

Como dicen los documentos para tolist():

Devuelve el array como una lista (posiblemente anidada).

Devuelve una copia de los datos del array como una lista Python (anidada). Partidas de datos se convierten al tipo de Python compatible más cercano.

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

 23
Author: DSM,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-07-19 13:31:37

Porque los elementos de una matriz NumPy no son ints nativos, sino de los propios tipos de NUmPy:

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

Puede utilizar un personalizado JSONEncoder para soportar 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))
 24
Author: phihag,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-07-19 17:11:37

El problema es que con la primera no se obtiene un int. Obtienes un numpy. int64. Que no puede ser serializado.

 1
Author: Stefano Borini,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-07-19 13:31:58