Reputation: 9868
I am trying to serialize a list of model object defined as:
class AnalysisInput(models.Model):
input_user = models.CharField(max_length=45)
input_title = models.CharField(max_length=45)
input_date = models.DateTimeField()
input_link = models.CharField(max_length=100)
I wrote a custom serializer (encoder) for json.dumps():
class AnalysisInputEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, AnalysisInput):
return { "input_id" : obj.id,
"input_user" : obj.input_user,
"input_title" : obj.input_title,
"input_date" : obj.input_date.isoformat(),
"input_link" : obj.input_link }
return json.JSONEncoder.default(self, obj)
When I serialize only one object, I am able to do it. When I try to serialize a list of object I get
[ objects..] is not JSON serializable
I searched but I didn't find where to work on.. I was thinking about writing a custom serializer also for list of model object.
Upvotes: 23
Views: 58357
Reputation: 381
The best way I found to serialize your Django models is by using django.core.serializers
to serialize your model list into JSON, XML, or YAML. No custom serialization code required! Documentation is here: https://docs.djangoproject.com/en/dev/topics/serialization/
Here is my implementation:
lead/models.py:
from django.db import models
class Lead(models.Model):
name = models.CharField(max_length=50)
email = models.CharField(max_length=256)
phone = models.CharField(max_length=20)
twitter_handle = models.CharField(max_length=20)
github_handle = models.CharField(max_length=20)
lead/views.py:
from django.http import HttpResponse
from django.core import serializers
from lead.models import Lead
def index(request):
leads_as_json = serializers.serialize('json', Lead.objects.all())
return HttpResponse(leads_as_json, content_type='application/json')
The end result:
[{"pk": 1, "model": "lead.lead", "fields": {"twitter_handle": "johndoe", "name": "John Doe", "phone": "1(234)567-8910", "email": "[email protected]", "github_handle": "johndoe"}}]
Upvotes: 22
Reputation: 4471
Simplest solution:
def index(request):
data = serializers.serialize('json', Product.objects.all())
return HttpResponse(data, content_type='application/json')
Upvotes: 2
Reputation: 1121216
A custom encoder is not called recursively. You are actually better off not using a custom encoder, and instead convert your objects to simple python types before serializing.
You could add a as_json
or similarly named method to your model and calling that every time you need a JSON result:
class AnalysisInput(models.Model):
input_user = models.CharField(max_length=45)
input_title = models.CharField(max_length=45)
input_date = models.DateTimeField()
input_link = models.CharField(max_length=100)
def as_json(self):
return dict(
input_id=self.id, input_user=self.input_user,
input_title=self.input_title,
input_date=self.input_date.isoformat(),
input_link=self.input_link)
Then in your view:
# one result
return HttpResponse(json.dumps(result.as_json()), content_type="application/json")
# a list of results
results = [ob.as_json() for ob in resultset]
return HttpResponse(json.dumps(results), content_type="application/json")
Upvotes: 50