python 瓶架:如何在JSON响应中返回datetime

fnvucqvd  于 2023-04-10  发布在  Python
关注(0)|答案(2)|浏览(104)

当我试图返回包含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

有没有一种简单的方法可以向bottle添加一个对象钩子,比如

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

转换datetime值?

20jt8wwn

20jt8wwn1#

有趣的问题!我可以看到几种方法来做到这一点。其中一种是编写一个自定义插件来 Package 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)

然后可以像这样使用:

@route('/hello')
def index(name):
    return {'test': datetime.datetime(2014, 2, 1, 0, 0)}

install(JSONDefaultPlugin())
run(host='localhost', port=8080)

并将给予如下输出:

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

另一种更短的方法是在示例化JSONPlugin类时简单地指定json_loads参数:

import json
from bson import json_util

install(JSONPlugin(json_dumps=lambda body: json.dumps(body, default=json_util.default)))

这会产生相同的结果。

后台

当您查看source code for bottle时,这一切都更有意义(为了简洁起见,下面删除了一些部分):

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

我们需要做的就是确保对dumps的调用接收到您希望提供的default关键字参数。

8gsdolmq

8gsdolmq2#

一些简短的补充:
1.如果您只喜欢使用标准库,则可以执行以下操作:

import json
from datetime import datetime
from functools import partial

from bottle import run

from bottle import JSONPlugin, Bottle

json_plugin = JSONPlugin(json_dumps=partial(json.dumps, default=str))
app = Bottle()
app.install(json_plugin)

1.如果您需要更复杂的datetime表示:

def json_serial(obj):
    """JSON serializer for objects not serializable by default json code"""

    if isinstance(obj, (datetime, date)):
        # NOT SO SOPHISTICATED, BUT BETTER THAN str
        # replace this with what ever format you need
        return obj.isoformat() 
    raise TypeError ("Type %s not serializable" % type(obj))

json_plugin = JSONPlugin(json_dumps=partial(json.dumps, default=json_serial))

1.最后,如果你喜欢简洁:由于JSON插件被插入到默认的Bottle示例中,因此您可以执行以下操作:

app = Bottle()
app.plugins[0].json_dumps = partial(json.dumps, default=str)

相关问题