TypeError:Python对象不是JSON可序列化的

时间:2016-04-11 17:43:16

标签: python json django object

我正在尝试使用Django中的json.dumps()将对象编码为json,但是当我传入python对象时,它会引发此错误。

TypeError: <OrgInvite: OrgInvite object> is not JSON serializable

我假设即使JSON只能编码某些数据类型,其中一种数据类型也是对象。我在Stack Overflow上读到另一个问题,解决这个问题的一个好方法是使用.__dict__从对象创建一个字典。我试过这个并且它说我的新字典中的一个键,_state不是序列化。我不知道这个_state键来自哪里,并且想知道有没有办法将我的对象转换为没有那个额外字段的字典,所以我可以将它编码为JSON?

模型:

class OrgInvite(models.Model):
    token = models.CharField(max_length=16, unique=True, null=False)
    account_id = models.ForeignKey(Account, on_delete=models.CASCADE, null=False)
    org_id = models.ForeignKey(Org, on_delete=models.CASCADE, null=False)
    used = models.BooleanField(default=False)
    is_admin = models.BooleanField(default=False)
    name = models.CharField(max_length=70)
    email = models.CharField(max_length=255)

观点:

def get_invite(token):
    if not token:
        raise Exception("Invitation token is not specified")

    invitation = OrgInvite.objects.get(token=token)
    if not invitation:
        raise Exception("Invitation token is invalid.")

    return invitation

def invite_accept_redirect(token):
    # """ -Redirects to the accept invite frontend view with pre-fetched data. """

    try:
        invite = get_invite(token)
        if not invite:
            raise Exception("Invitation token is invalid")
        if invite.used:
            invite = {'used': True}
    except:
        invite = {'invalid': True}
        raise Exception("Resource not found.")

    base = "home/accept"

    url = '{}/{}?data={}'.format(base, token, urllib.quote_plus(json.dumps(invite.__dict__)))

    return redirect(url)

控制台:

>>> oi = OrgInvite.objects.get(token=100) 
>>> oi
<OrgInvite: OrgInvite object>
>>> oix = oi.__dict__
>>> oix
{'used': False, 'name': u'', '_state': <django.db.models.base.ModelState object at 0x10377a610>, 'email': u'', 'token': u'100', 'org_id_id': 101, 'account_id_id': 301, 'is_admin': False, 'id': 1}
>>> json.dumps(oix)
Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "/usr/local/Cellar/python/2.7.11/Frameworks/Python.framework/Versions/2.7/lib/python2.7/json/__init__.py", line 244, in dumps
    return _default_encoder.encode(obj)
  File "/usr/local/Cellar/python/2.7.11/Frameworks/Python.framework/Versions/2.7/lib/python2.7/json/encoder.py", line 207, in encode
    chunks = self.iterencode(o, _one_shot=True)
  File "/usr/local/Cellar/python/2.7.11/Frameworks/Python.framework/Versions/2.7/lib/python2.7/json/encoder.py", line 270, in iterencode
    return _iterencode(o, 0)
  File "/usr/local/Cellar/python/2.7.11/Frameworks/Python.framework/Versions/2.7/lib/python2.7/json/encoder.py", line 184, in default
    raise TypeError(repr(o) + " is not JSON serializable")
TypeError: <django.db.models.base.ModelState object at 0x10377a610> is not JSON serializable

3 个答案:

答案 0 :(得分:5)

__dict__提供了实例的所有属性,但您并不想要所有额外的行李 - 为了序列化,您只对这些字段感兴趣。

您的模型不包含任何特殊内容,因此内置辅助函数model_to_dict应该足以满足您的需求:

import json
from django.forms.models import model_to_dict

oi = OrgInvite.objects.get(token=100) 
oi_dict = model_to_dict(oi)
oi_serialized = json.dumps(oi_dict)

您的示例很简单,只包含CharFieldBooleanFieldForeignKey,我们可以将其全部转储到json

对于更复杂的模型,您可以考虑编写自己的serializer。在这种情况下,我建议使用流行的django-rest-framework,它可以为您完成所有工作。

from rest_framework import serializers

class OrgInviteSerializer(serializers.ModelSerializer):
    class Meta:
        model = OrgInvite
        fields = '__all__'

答案 1 :(得分:1)

如果您执行invite.__dict__,它将为您提供与一个invite对象相关的所有数据的字典。但是,dict的值不一定是原始类型,而是对象(ModelState只是其中之一)。序列化不仅不起作用,因为json不接受python对象,但你也可以序列化大量未使用的元数据。

查看json official website以查看json可序列化的数据类型。修复将使用django model serializer,或手动创建符合json格式的字典。

答案 2 :(得分:0)

object不是其中之一。字典,列表(可能是元组),浮点数,字符串,整数,bool和None我相信是Python可以本地序列化为JSON的类型。

然而,它看起来像Django has some built-in serializers可能适合你。

我猜这个

from django.core import serializers
data = serializers.serialize("json", OrgInvite.objects.filter(token=100))

应该适合你