一尘不染

Python JSON编码器支持日期时间?

mysql

有什么优雅的方法可以使Python JSON编码器支持日期时间?一些第三者模块还是容易破解?

我正在使用tornado的数据库包装程序从db获取一些行以生成json。查询结果包括一个常规的MySQL时间戳列。

令人讨厌的是,Python的默认json编码器不支持自己的日期时间类型,这种类型在所有类型的数据库查询中都很常见。

我不想修改Python自己的json编码器。有什么好的做法吗?非常感谢!

ps:通过修改Python JSON编码器默认方法,我发现了一个肮脏的骇客:

更改:

def default(self, o):
    raise TypeError(repr(o) + " is not JSON serializable")

至:

def default(self, o):
    from datetime import date
    from datetime import datetime
    if isinstance(o, datetime):
        return o.isoformat()
    elif isinstance(o, date):
        return o.isoformat()
    else:
        raise TypeError(repr(o) + " is not JSON serializable")

好吧,这将仅是针对开发环境的临时解决方案。

但是对于长期解决方案或生产环境而言,这非常丑陋,并且每次部署到新服务器时都必须进行修改。

有没有更好的办法?我不想修改Python代码本身,也不想修改Tornado源代码。我可以使用自己的项目代码来做到这一点吗?最好以一个步伐。

非常感谢!


阅读 373

收藏
2020-05-17

共1个答案

一尘不染

该文档建议将
JSONEncoder子类化并实现您自己的默认方法。似乎您基本上就在那儿,这不是“肮脏的骇客”。

日期未由默认编码器处理的原因是,JSON中没有日期的标准表示形式。有人使用该格式/Date(1198908717056)/,但我个人更喜欢ISO格式。

import json
import datetime


class DateTimeEncoder(json.JSONEncoder):

    def default(self, obj):
        if isinstance(obj, (datetime.datetime, datetime.date, datetime.time)):
            return obj.isoformat()
        elif isinstance(obj, datetime.timedelta):
            return (datetime.datetime.min + obj).time().isoformat()

        return super(DateTimeEncoder, self).default(obj)

now = datetime.datetime.now()
encoder = DateTimeEncoder()
encoder.encode({"datetime": now, "date": now.date(), "time": now.time()})
> {"datetime": "2019-07-02T16:17:09.990126", "date": "2019-07-02", "time": "16:17:09.990126"}
2020-05-17