【问题标题】:Weird TypeError from json.dumps来自 json.dumps 的奇怪 TypeError
【发布时间】:2014-11-09 02:04:03
【问题描述】:

在 python 3.4.0 中,使用 json.dumps() 在一种情况下会引发 TypeError,但在另一种情况下就像魅力一样(我认为这与第一种情况相同)。

我有一个字典,其中键是字符串,值是数字和其他字典(例如 {'x': 1.234, 'y': -5.678, 'z': {'a': 4, 'b': 0, 'c': -6}})。

这失败了(堆栈跟踪不是来自这个特定的代码 sn-p,而是来自我不会在此处粘贴的较大脚本,但它本质上是相同的):

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

306x 中其他内部字典之一中的值之一。它并不总是相同的数字,有时它是字典中包含的不同数字,显然是因为字典的无序性。

但是,这就像一个魅力:

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

谁能告诉我为什么会发生这种情况或可能是什么原因?最令人困惑的部分是这两个 dicts(原始的和通过评估原始的表示获得的)是相等的,但是 dumps() 函数对它们每个的行为不同。

【问题讨论】:

  • 你确定它是一个实际的整数,而不是repr306 的其他对象吗?
  • JSON 告诉您306不是它支持的类型。事实上,它有一个 看起来 像整数的表示形式,这显然是一种误导,因为如果它真的只是一个整数,你就不会得到这个异常。你能告诉我们type(the_306_value) 是什么吗?
  • @jonrsharpe @MartijnPieters 这是numpy.int64 所以这似乎是原因。我的错,谢谢!

标签: python json python-3.x numpy dictionary


【解决方案1】:

如你所见,numpy int64 数据类型不能直接序列化成 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

然而,Python 整数——包括更长的整数——可以被序列化和反序列化:

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

所以使用 numpy,你可以直接转换成 Python 数据结构然后序列化:

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

【讨论】:

    【解决方案2】:

    原因是dict里面的数字不是普通的pythonints而是numpy.in64s,显然json编码器不支持。

    【讨论】:

      猜你喜欢
      • 2016-05-11
      • 2011-01-17
      • 2020-02-10
      • 2015-05-21
      • 2010-10-27
      • 2014-01-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多