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?
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.
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))
The problem is that with the first you don't get an int. You get a numpy.int64. That cannot be serialized.