简体   繁体   English

Bottle框架:如何在JSON响应中返回datetime

[英]Bottle framework: how to return datetime in JSON response

When I try to return JSON containing datetime value, I'm getting 当我尝试返回包含datetime值的JSON时,我得到了

  File "/usr/lib/python2.7/json/encoder.py", line 178, in default
    raise TypeError(repr(o) + " is not JSON serializable")
TypeError: datetime.datetime(2014, 2, 1, 0, 0) is not JSON serializable

Which is normal. 这是正常的。 Is there an easy way to add an object hook to bottle like 是否有一种简单的方法可以将对象挂钩添加到bottle

from bson import json_util
import json
json.dumps(anObject, default=json_util.default)

to get datetime values converted? 获取datetime值转换?

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 : 一个是编写一个包装JSONPlugin的自定义插件:

from bottle import route, run, install, JSONPlugin
from bson import json_util

class 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: 另一种更短的方法是在实例化JSONPlugin类时简单地指定json_loads参数:

import json
from bson import json_util

install(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. 我们需要做的就是确保对dumps的调用接收到您希望提供的default关键字参数。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM