Most people encountering the Ajax components of Django for the first time usually encounter this pairing:

from django.utils import simplejson
...
return HttpResponse(simplejson.dumps(some_python_obj))

For most applications, this is enough.  But I'm especially fond of iterators, generators, functors and closures, dense components that express one thought well: the structure of a tree, or the rows of a database, to be sent to the browser.  The routine dumps() doesn't understand any of those things, but with a simple addition, you can plug them into your code and be on your way without headache.  Dumps() just calls JSONEncoder(), and JSONEncoder has a routine for extending its functionality.

The routine is to override a method named default() (why "default?" I have no idea) and add the object types and signatures you want to send to the browser.  Normally, this exists for you to provide custom "object to JSON" handlers for your objects, but there's nothing custom about iterators, generators, functors and closures.  They are native Python objects.

from django.utils.simplejson.encoder import JSONEncoder

class ExtJsonEncoder(JSONEncoder):
    def default(self, c):
        # Handles generators and iterators
        if hasattr(c, '__iter__'):
            return [i for i in c]

        # Handles closures and functors
        if hasattr(c, '__call__'):
            return c()

        return JSONEncoder.default(self, c)

This exploits the OO nature of Python code: everything is an object, and I'm just checking to see if the object passed in has the interface needed to treat it like an iterator or a function.  If it's an iterator, iterate it; if it's a function, call it. Normally I like my code to be sensible, so I devolve this into a function, just like dumps():

from django.utils import simplejson

def json(s, **kw):
    kw.update({'cls': ExtJsonEncoder})
    return simplejson.dumps(s, **kw)

To show this in use, I'll use the Tag() tree class I've been working on this week.  First, here's the "Django Tree to Dojo Tree JSON" as a functor (a functor is a class that includes a method named call() in its interface, and a reference to an object of that class can be called like a function):

class TreeToJson:
    def __init__(self, roots):
        self.roots = roots

    def _index(self, nodes):
        def _item(node):
            t = { 'id': node.id,
                  'name': node.name,
                  'top': node.is_root()}
            if not node.is_leaf():
                t.update({'children': self._index(node.get_children())})
            return t

        return [_item(node) for node in nodes]

    def __call__(self):
        return self._index(self.roots)

print json(TreeToJson(Tag.get_root_nodes())

The class TreeToJson completely encapsulates the process of converting a django-treebeard tree into a dojo tree structure here. As an alternative, here it is as a generator:

def treetojson(roots):
    def _item(node):
        t = { 'id': node.id,
              'name': node.name,
              'top': node.is_root()}
        if not node.is_leaf():
            t.update({'children': _tree(node.get_children())})
        return t

    def _tree(nodes):
        for node in nodes:
            yield _item(node)

    return _tree(roots)

print json(treetojson(Tag.get_root_nodes()))

Again, the function treetojson completely encapsulates the process of converting a django-treebeard tree into a dojo tree.  Both of these work quite nicely, spewing out a Javascript Object ready to be eval'd and processed on the client.

Now, obviously, my implementation of ExtJsonEncoder has its opinions: it prioritizes iterators over functions.  But I've been using this implementation with this priority with Webware and EXT-JS (and a handwritten version of simplejson) and I have yet to encounter a case where a class had both iter() and call() defined or needed the latter prioritized.