Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does json.dumps(list(np.arange(5))) fail while json.dumps(np.arange(5).tolist()) works

I noticed this problem when a computer running Ubuntu was updated recently and the default version of Python changed to 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  

Is there a difference between list() and the tolist() methd of a numpy array?

like image 696
azeey Avatar asked Jul 19 '12 13:07

azeey


People also ask

What is JSON dump and dumps?

1. json. dump() method used to write Python serialized object as JSON formatted data into a file. json. dumps() method is used to encodes any Python object into JSON formatted String.

How do I save a NumPy array as JSON?

Use the cls kwarg of the json. dump() and json. dumps() method to call our custom JSON Encoder, which will convert NumPy array into JSON formatted data. To serialize Numpy array into JSON we need to convert it into a list structure using a tolist() function.


2 Answers

It looks like the tolist() method turns the numpy int32 (or whatever size you have) back into an int, which JSON knows what to do with:

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

As the docs say for tolist():

Return the array as a (possibly nested) list.

Return a copy of the array data as a (nested) Python list. Data items are converted to the nearest compatible Python type.

The last line makes the difference here.

like image 122
DSM Avatar answered Oct 19 '22 18:10

DSM


Because the elements of a NumPy array are not native ints, but of NUmPy's own types:

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

You can use a custom JSONEncoder to support the ndarray type returned by 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)) 
like image 30
phihag Avatar answered Oct 19 '22 20:10

phihag