it-swarm.com.ru

TypeError: объект Python не поддерживает сериализацию в формате JSON

Я пытаюсь закодировать объект в json с помощью json.dumps() в Django, однако, когда я передаю объект python, возникает эта ошибка. 

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

Я предполагал, что, хотя JSON может кодировать только определенные типы данных, один из этих типов данных был объектами. Я прочитал еще один вопрос о переполнении стека: хороший способ обойти это - создать словарь из объекта с помощью .__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
5
JBT

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

Ваш пример был простым, он содержал только CharField, BooleanField и ForeignKey, все из которых мы можем легко перевести в json

Для более сложных моделей вы можете написать собственный сериализатор . В этом случае я рекомендую использовать популярный Django-rest-framework , который сделает всю работу за вас. 

from rest_framework import serializers

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

Если вы выполните invite.__dict__, он предоставит вам словарь всех данных, связанных с одним объектом invite. Однако значения dict не обязательно являются примитивными типами, но также и объектами (ModelState - только один из них). Сериализация, которая не только не работает, потому что json не принимает объекты Python, но вы также можете сериализовать много метаданных, которые не используются.

Проверьте официальный сайт json , чтобы увидеть, какие типы данных json сериализуемы. Исправление будет либо с использованием сериализатора модели Django , либо вручную создавать dict, соответствующий формату json.

1
Shang Wang

object не относится к таким типам. Словари, списки (возможно, кортежи), числа с плавающей запятой, строки, целые числа, bools и None I believe - это типы, которые Python может сериализовать в JSON.

Тем не менее, похоже, что Django имеет несколько встроенных сериализаторов , которые могут работать для вас.

Я предполагаю, что 

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

должен работать на вас

0
Wayne Werner