Django: "TypeError: []不能序列化为JSON" 为什么?

36 投票
3 回答
49463 浏览
提问于 2025-04-15 19:08

这个错误是怎么出现的呢?我输入了这个:

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()方法,当它为空的时候返回'[]'这样的字符串,还是其他什么奇怪的原因吗?

3 个回答

4

正如Vinay所提到的,即使你把数据转换成列表,序列化(把数据转换成可以存储或传输的格式)通常还是会失败。对我来说,序列化在处理日期时间字段(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这个内置函数,如果你需要在序列化时获取对象类型的信息,它也可能会很有用。

6

这真让人头疼。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'
60

查询集(Querysets)默认是不能直接转换成可存储格式的。如果你尝试用 list(self.items) 而不是直接用 self.items,这样做应该没问题,只要这些项目本身是可以转换成JSON格式的。

更新:即使查询集不是空的,它也会抛出一个异常。不过我觉得这不会被认为是Django的一个bug,当然你可以试试;最简单的解决办法就是用 list(qs) 强制转换,就像我之前说的那样。

撰写回答