类型错误:Python 对象不是 JSON 可序列化的

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/36555602/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 18:02:06  来源:igfitidea点击:

TypeError: Python object is not JSON serializable

pythonjsondjangoobject

提问by TJB

I am trying to encode an object into json using json.dumps()in Django, however when I pass in a python object, it raises this error.

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

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

I was under the assumption that even though JSON can only encode certain data types, one of those data types were objects. I read another question on Stack Overflow that a good way to get around this is by creating a dictionary out of the object using .__dict__I tried this and it is saying that one of the keys in my new dictionary, _state is not serializable. I am not sure where this _state key came from, and was wondering is there a way to convert my object into a dictionary without that extra field, so I can encode it into JSON ?

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

model:

模型:

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)

view:

看法:

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)

console:

安慰:

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

采纳答案by wim

The __dict__gives all the attributes of the instance, but you don't want all that extra baggage - for the purposes of serialization, you are only interested in the fields.

__dict__给出了实例的所有属性,但你不希望所有的微胖-序列化的目的,你只关心的领域。

Your model does not contain anything special so the built-in helper function model_to_dictshould be enough for your needs:

您的模型不包含任何特殊内容,因此内置的辅助函数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)

Your example was simple, only containing CharField, BooleanField, and ForeignKeyall of which we can dump to jsontrivially.

您的示例很简单,只包含CharField,BooleanFieldForeignKey我们可以轻松转储的所有内容json

For more complicated models, you might consider writing your own serializer. In this case, I recommend using the popular django-rest-frameworkwhich does all the work for you.

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

from rest_framework import serializers

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

回答by Shang Wang

If you do invite.__dict__, it's going to give you a dictionary of all data related to one inviteobject. However, the dict's values are not necessarily primitive types, but objects as well(ModelStateis just one of them). Serializing that would not only not working because json doesn't accept python objects, but you could also serialize a lot of meta data that's not used.

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

Check out json official websiteto see what data types are json serializable. The fix would be either using django model serializer, or manually create a dict that in compliance to json format.

查看json官网,看看哪些数据类型是json可序列化的。修复方法是使用django 模型序列化程序,或者手动创建一个符合 json 格式的字典。

回答by Wayne Werner

objectis not one of those types. Dictionaries, lists (maybe tuples), floats, strings, integers, bools, and None I believeare the types that Python can serialize into JSON natively.

object不是这些类型之一。字典、列表(可能是元组)、浮点数、字符串、整数、布尔值和 None 我相信是 Python 可以本地序列化为 JSON 的类型。

However, it looks like Django has some built-in serializersthat may work for you.

但是,看起来 Django有一些可能适合您的内置序列化程序。

I'm guessing that

我猜

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

should work for you

应该为你工作