【问题标题】:Django: "TypeError: [] is not JSON serializable" Why?Django:“TypeError:[] 不是 JSON 可序列化的”为什么?
【发布时间】:2011-01-15 15:01:58
【问题描述】:

怎么会引发这个错误?我输入了这个:

def json(self):
    return json.dumps(
        {
            'items': self.items
        }
    )

并得到了那个错误(因为 self.items 是一个空的查询集(Django)

然后,

def json(self):
    return json.dumps(
        {
            'items': []  # Pass in empty list to prove that the error was idiotic.
        }
    )

工作正常(这至少证明错误消息毫无价值)

这是因为查询集定义了 repr() 并在它为空或类似荒谬的情况下将 '[]' 作为字符串返回?

【问题讨论】:

  • 你为什么要定义一个与你正在使用的模块同名的函数?
  • @gnibbler 这不是一个函数。这是一种方法,我将它用作@property(在我的示例中没有包含它)。
  • 我喜欢回顾我的自鸣得意,...the error was idiotic.

标签: python django json


【解决方案1】:

查询集不是开箱即用的可序列化。如果您尝试使用 list(self.items) 而不仅仅是 self.items,只要项目本身是 JSON 可序列化的,这应该可以工作。

更新:即使不为空也会引发异常。我不认为它会被接受为 Django 错误,尽管您当然可以尝试;正如我已经说过的,最简单的答案是使用list(qs) 强制评估。

【讨论】:

  • +1。这就是答案。您正在使用 list(queryset) 强制立即评估查询集。底层数据,以列表的形式,是可序列化的;查询集本身不是。 docs.djangoproject.com/en/dev/ref/models/querysets/#id1
  • 好答案。谢谢。顺便说一句,这似乎是一个错误。我要开始买票了。 Django 的序列化器用于序列化 Django 查询集。如果它在为空时引发异常,那就是一个错误。
  • @orokusaki,这对我来说并不像一个错误。有时你想要对象。有时你想要字符串。 Django 让你选择。对于所有 Django 字段,这是一个更适合我的 Pythonic 替代方案:[str(obj) for obj in Model.objects.values()]see below
【解决方案2】:

这很令人沮丧。 Django 的序列化抱怨所有不是查询集的东西,而 json.dumps 抱怨来自 Django 的 ORM 支持的对象。

>>> from cluster.models import Account
>>> import json
>>> json.dumps(Account.objects.all()[0])
Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/json/__init__.py", line 231, in dumps
    return _default_encoder.encode(obj)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/json/encoder.py", line 201, in encode
    chunks = self.iterencode(o, _one_shot=True)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/json/encoder.py", line 264, in iterencode
    return _iterencode(o, 0)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/json/encoder.py", line 178, in default
    raise TypeError(repr(o) + " is not JSON serializable")
TypeError: <Account: 9de5-2653-000d-81a3 => foo@bar.net> is not JSON serializable

对比

>>> serializers.serialize("json", [clusters])
Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/django/core/serializers/__init__.py", line 91, in serialize
    s.serialize(queryset, **options)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/django/core/serializers/base.py", line 41, in serialize
    for field in obj._meta.local_fields:
AttributeError: 'QuerySet' object has no attribute '_meta'

【讨论】:

    【解决方案3】:

    正如 Vinay 指出的那样,即使您投射到列表中,序列化通常仍然会失败。对我来说,DateTimeField 元素(datetime.datetime 对象)的序列化失败,即使我要求ValuesQuerySet(类似列表)和.values()。对我来说,解决方案是简单的理解。

    json.dumps([str(obj) for obj in Model.objects.values()]);
    

    在你的情况下,那将是

    return json.dumps({k: str(v) for k, v in self.__dict__.items()})
    

    str 的魔力拯救了这一天。如果您在序列化中需要对象类型信息,则内置的 repr 也可能会有所帮助。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-02-25
      • 2017-10-24
      • 2016-08-02
      • 2019-02-08
      • 2013-05-11
      • 2018-03-05
      • 2020-12-13
      • 2014-08-13
      相关资源
      最近更新 更多