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.
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 ?
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
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.
Your model does not contain anything special so the built-in helper function model_to_dict
should be enough for your needs:
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 ForeignKey
all of which we can dump to json
trivially.
For more complicated models, you might consider writing your own serializer. In this case, I recommend using the popular django-rest-framework which does all the work for you.
from rest_framework import serializers
class OrgInviteSerializer(serializers.ModelSerializer):
class Meta:
model = OrgInvite
fields = '__all__'
If you do invite.__dict__
, it's going to give you a dictionary of all data related to one invite
object. However, the dict's values are not necessarily primitive types, but objects as well(ModelState
is 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.
Check out json official website to 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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With