Weird TypeError by json.dumps

In python 3.4.0, use is json.dumps()

throwing me a TypeError in one case, but works like a charm in another case (which is equivalent to the first in my opinion).

I have a dict where keys are strings and values ​​are numbers and other dict (like {'x': 1.234, 'y': -5.678, 'z': {'a': 4, 'b': 0, 'c': -6}}

).

This fails (stacktrace is not relevant to this piece of code, but from my larger script, which I won't be pasting here, but it's very important):

>>> x = dict(foo()) # obtain the data and make a new dict of it to really be sure
>>> import json
>>> json.dumps(x)
Traceback (most recent call last):
  File "/mnt/data/gandalv/progs/pycharm-3.4/helpers/pydev/pydevd.py", line 1733, in <module>
    debugger.run(setup['file'], None, None)
  File "/mnt/data/gandalv/progs/pycharm-3.4/helpers/pydev/pydevd.py", line 1226, in run
    pydev_imports.execfile(file, globals, locals)  # execute the script
  File "/mnt/data/gandalv/progs/pycharm-3.4/helpers/pydev/_pydev_execfile.py", line 38, in execfile
    exec(compile(contents+"\n", file, 'exec'), glob, loc) #execute the script
  File "/mnt/data/gandalv/School/PhD/Other work/Krachy/code/recalculate.py", line 54, in <module>
    ls[1] = json.dumps(f)
  File "/usr/lib/python3.4/json/__init__.py", line 230, in dumps
    return _default_encoder.encode(obj)
  File "/usr/lib/python3.4/json/encoder.py", line 192, in encode
    chunks = self.iterencode(o, _one_shot=True)
  File "/usr/lib/python3.4/json/encoder.py", line 250, in iterencode
    return _iterencode(o, 0)
  File "/usr/lib/python3.4/json/encoder.py", line 173, in default
    raise TypeError(repr(o) + " is not JSON serializable")
TypeError: 306 is not JSON serializable

      

306

is one of the values ​​in one of the internal dicts in x

. It is not always the same number, sometimes it is a different number contained in the dict, apparently due to the disordered dict.

However, this works like a charm:

>>> x = foo() # obtain the data and make a new dict of it to really be sure
>>> import ast
>>> import json
>>> x2 = ast.literal_eval(repr(x))
>>> x == x2
True
>>> json.dumps(x2)
"{...}" # the json representation of dict as it should be

      

Can someone please tell me why this is happening or what could be causing it? The most confusing part is that these two dicts (the original and the one obtained by evaluating the original representation) are equal, but the function dumps()

behaves differently for each one.

+3


source to share


2 answers


The reason was that the numbers inside dict

were not regular python int

, but numpy.in64

which apparently are not supported by the json encoder.



+3


source


As you saw, numpy int64 data types are not serialized directly to json:

>>> import numpy as np
>>> import json
>>> a=np.zeros(3, dtype=np.int64)
>>> a[0]=-9223372036854775808
>>> a[2]=9223372036854775807
>>> jstr=json.dumps(a)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/Cellar/python3/3.4.1/Frameworks/Python.framework/Versions/3.4/lib/python3.4/json/__init__.py", line 230, in dumps
    return _default_encoder.encode(obj)
  File "/usr/local/Cellar/python3/3.4.1/Frameworks/Python.framework/Versions/3.4/lib/python3.4/json/encoder.py", line 192, in encode
    chunks = self.iterencode(o, _one_shot=True)
  File "/usr/local/Cellar/python3/3.4.1/Frameworks/Python.framework/Versions/3.4/lib/python3.4/json/encoder.py", line 250, in iterencode
    return _iterencode(o, 0)
  File "/usr/local/Cellar/python3/3.4.1/Frameworks/Python.framework/Versions/3.4/lib/python3.4/json/encoder.py", line 173, in default
    raise TypeError(repr(o) + " is not JSON serializable")
TypeError: array([-9223372036854775808,                    0, 9223372036854775807]) is not JSON serializable

      

However, Python integers, including longer integers, can be serialized and deserialized:



>>> json.loads(json.dumps(2**123))==2**123
True

      

So with numpy, you can directly convert to Python data structures and then serialize:

>>> jstr=json.dumps(a.tolist())
>>> b=np.array(json.loads(jstr))
>>> np.array_equal(a,b)
True

      

+1


source







All Articles