JSON Serializing Django Models with simplejson

38,816

Solution 1

I would go with extending simplejson. Basically, you want to plug in django's serialization when the JSON encoder encounters a QuerySet. You could use something like:

from json import dumps, loads, JSONEncoder

from django.core.serializers import serialize
from django.db.models.query import QuerySet
from django.utils.functional import curry

class DjangoJSONEncoder(JSONEncoder):
    def default(self, obj):
        if isinstance(obj, QuerySet):
            # `default` must return a python serializable
            # structure, the easiest way is to load the JSON
            # string produced by `serialize` and return it
            return loads(serialize('json', obj))
        return JSONEncoder.default(self,obj)

# partial function, we can now use dumps(my_dict) instead
# of dumps(my_dict, cls=DjangoJSONEncoder)
dumps = curry(dumps, cls=DjangoJSONEncoder)

For more info on default method, have a look at simplejson documentation. Put that in a python module, then import dumps and you're good to go. But note that this function will only help you serializing QuerySet instances, not Model instances directly.

Solution 2

A really flexible way to serialize most structures in django is to use the serializer class found here

Solution 3

based on Clement's answer, I did this to get models into JSON as well.

def toJSON(obj):
   if isinstance(obj, QuerySet):
       return simplejson.dumps(obj, cls=DjangoJSONEncoder)
   if isinstance(obj, models.Model):
       #do the same as above by making it a queryset first
       set_obj = [obj]
       set_str = simplejson.dumps(simplejson.loads(serialize('json', set_obj)))
       #eliminate brackets in the beginning and the end 
       str_obj = set_str[1:len(set_str)-2]
   return str_obj
Share:
38,816
Zack
Author by

Zack

Updated on July 09, 2022

Comments

  • Zack
    Zack almost 2 years

    I'd like to use simplejson to serialize a Django model. Django's serializer doesn't support dictionaries... and simplejson doesn't support Django Querysets. This is quite a conundrum.

    In the model there's sponsors that have a Foreign Key to sponsor level, I'm trying to group all the sponsors that belong to a certain sponsor level together. Here's the code that generates the list:

    from django.shortcuts import get_list_or_404
    from special_event.models import Sponsor, SponsorLevel
    
    sponsor_dict = {}
    
    roadie_sponsors = get_list_or_404(Sponsor, level__category = SponsorLevel.ROADIE_CHOICE)
    
    for item in roadie_sponsors:
        try:
            sponsor_dict[item.level.name].append(item)
        except KeyError:
            sponsor_dict[item.level.name] = [item]
    

    Here's what sponsor_dict looks like once it's "made"

    {
        'Fan': [<Sponsor: Fan Sponsor>], 
        'VIP': [<Sponsor: VIP Sponsor>],
        'Groupie': [<Sponsor: Groupie Sponsor>],
        'Silver': [<Sponsor: Silver Sponsor>],
        'Bronze': [<Sponsor: Another Bronze Sponsor>, <Sponsor: Bronze Sponsor>]
    }
    

    I only added one sponsor in each level, except for bronze, just to show how it works. All I want to do is get it "all" into JSON so jQuery can interpret it easily. Can Django's other serializers (like XML or YAML) accomplish this? Can I "extend" the Django JSON Serializer to handle dictionaries or "extend" simplejson to handle Django QuerySet objects?

  • Pickels
    Pickels over 13 years
    If you have a question you need to click the 'ask question' button at the top right. The 'Your Answer' form is used to post answers.
  • jcage
    jcage over 13 years
    My apologies. I only intended it to compliment the topic, since the main answer makes note of its inability to serialize objects. This goal is accomplished, since the code does work. My question about it being a good a idea or bad one was meant to invite discussion about better integration, and certainly not anyone's scorn
  • Glycerine
    Glycerine over 12 years
    Just implemented this. It's Brilliant! This script deserves more recognition.
  • stormlifter
    stormlifter about 12 years
    This is a very simple and adaptable solution.
  • Alison R.
    Alison R. over 11 years
    Curious to see this based upon the comments, but the page is gone. Anyone know if this is still around anywhere?
  • Nate Pinchot
    Nate Pinchot about 11 years