Bottle framework: how to return datetime in JSON response Bottle framework: how to return datetime in JSON response json json

Bottle framework: how to return datetime in JSON response


Interesting question! I can see a couple of ways of doing this. The one would be to write a custom plugin that wraps the JSONPlugin:

from bottle import route, run, install, JSONPluginfrom bson import json_utilclass JSONDefaultPlugin(JSONPlugin):    def __init__(self):        super(JSONDefaultPlugin, self).__init__()        self.plain_dump = self.json_dumps        self.json_dumps = lambda body: self.plain_dump(body, default=json_util.default)

Which can then be used like this:

@route('/hello')def index(name):    return {'test': datetime.datetime(2014, 2, 1, 0, 0)}install(JSONDefaultPlugin())run(host='localhost', port=8080)

And will give output like this:

{"test": {"$date": 1391212800000}}

Another, shorter, way is to simply specify the json_loads parameter when instantiating the JSONPlugin class:

import jsonfrom bson import json_utilinstall(JSONPlugin(json_dumps=lambda body: json.dumps(body, default=json_util.default)))

This produces the same result.

Background

This all makes a little more sense when you look at the source code for bottle (some parts removed below for brevity):

class JSONPlugin(object):    name = 'json'    api  = 2    def __init__(self, json_dumps=json_dumps):        self.json_dumps = json_dumps    def apply(self, callback, route):        dumps = self.json_dumps        if not dumps: return callback        def wrapper(*a, **ka):            ...             if isinstance(rv, dict):                ...            elif isinstance(rv, HTTPResponse) and isinstance(rv.body, dict):                rv.body = dumps(rv.body)                rv.content_type = 'application/json'            return rv        return wrapper

All we need to do is make sure the call to dumps there receives the default keyword argument you wish to provide.