A Python web framework that makes the most of the filesystem.
Simplates are the main attraction.

JSON Simplates

Aspen has special support for using simplates to serve JSON resources. Files with an extension of .json.spt will be specially processed as a JSON simplate. While normal simplates can have up to three pages, a JSON simplate only has one or two pages (you’ll get a LoadError if there is more than one page separator in a JSON simplate).


A static JSON simplate has only one page (i.e., it has no page breaks at all). It is served as a static file, and it’s up to you to make sure that it is valid JSON (only double quotes, etc.).


A dynamic JSON simplate has two pages (one page break). The first is a startup Python page, and the second is a request-time Python page. There is never a template page for a JSON simplate.

For dynamic JSON simplates, if you set response.body in the second page to something besides a str or unicode, then Aspen will automatically call json.dumps on response.body for you. The result will be used as the new response.body.

Aspen will serialize instances of the following types. Instances of any other type will raise TypeError, so be sure to pre-process your output if it contains anything else.


Make a greetings.json.spt file with this content:

import random
n = random.choice(range(10))
extra_excitement = "!" * n
response.body = {'Greetings': 'program!' + extra_excitement}

Notice that there is no third page. Now hit this in your browser:

Configuring Content-Type

By default Aspen sets Content-Type to application/json for JSON simplates. If you would like to use something else while preserving special JSON simplate handling, don’t use the normal mime.types configuration file. Aspen uses the mime.types mapping to determine that a simplate is a JSON simplate (actually, any file with an extension that you configure to have a mimetype of application/json will be treated as a JSON simplate). Instead, you should set the media_type_json key in, like so:

website.media_type_json = "application/javascript"

If you need to bypass special JSON simplate handling altogether, you can use mime.types to set the json extension to something besides application/json that browsers will still process as JSON:

application/javascript     json

This behavior holds true for both static and dynamic JSON simplates.

Supported JSON Libraries

Aspen will prefer simplejson if it is available, falling back to the standard library’s json module, which was added in Python 2.6. The latter is a more or less out-of-date version of the former. It also doesn’t have any C speedups. If Aspen can’t find either, then dynamic JSON simplates will raise an ImportError, though static JSON simplates will still work.

Custom Encoders

It’s fairly common to want to add encoders for custom classes or classes otherwise unknown to one or another version of simplejson. To this end, Aspen provides an API to manage a registry of encoders. These functions can be imported from aspen.json:

def register_encoder(cls, encode):
    """Register the encode function for cls.

    An encoder should take an instance of cls and return something
    basically serializable (strings, lists, dictionaries).


def unregister_encoder(cls):
    """Given a class, remove any encoder that has been registered for it.

These functions don’t affect the underlying simplejson library, only the Aspen abstraction layer. So if for example you have a simplejson that knows about Decimal objects (support for which was added in version 2.1 of the library), then if you register a custom encoder for Decimals, Aspen will use that where appropriate, and if you unregister it, the underlying implementation will be used again. Furthermore, if you use the simplejson library directly, the encoders registered with Aspen won’t be used at all.