使用 Flask 的 jsonify 时,将 datetime.date 保持为 'yyyy-mm-dd' 格式

Posted

技术标签:

【中文标题】使用 Flask 的 jsonify 时,将 datetime.date 保持为 \'yyyy-mm-dd\' 格式【英文标题】:Keep a datetime.date in 'yyyy-mm-dd' format when using Flask's jsonify使用 Flask 的 jsonify 时,将 datetime.date 保持为 'yyyy-mm-dd' 格式 【发布时间】:2017-09-25 14:08:43 【问题描述】:

由于某种原因,jsonify 函数将我的datetime.date 转换为似乎是 HTTP 日期的内容。使用jsonify时如何保持yyyy-mm-dd格式的日期?

test_date = datetime.date(2017, 4, 27)
print(test_date)  # 2017-04-27
test_date_jsonify = jsonify(test_date)
print(test_date_jsonify.get_data(as_text=True))  # Thu, 27 Apr 2017 00:00:00 GMT

按照 cmets 中的建议,使用 jsonify(str(test_date)) 会返回所需的格式。但是,请考虑以下情况:

test_dict = "name": "name1", "date":datetime.date(2017, 4, 27)
print(test_dict) # "name": "name1", "date":datetime.date(2017, 4, 27)

test_dict_jsonify = jsonify(test_dict)
print(test_dict_jsonify.get_data(as_text=True)) # "date": "Thu, 27 Apr 2017 00:00:00 GMT", "name": "name1"

test_dict_jsonify = jsonify(str(test_dict))
print(test_dict_jsonify.get_data(as_text=True)) # ""date": datetime.date(2017, 4, 27), "name": "name1""

在这种情况下,str() 解决方案不起作用。

【问题讨论】:

将其序列化为字符串? 我不太明白你的意思。 jsonify(str(test_date)) 当你打印一个对象时,该对象的__str__方法被调用,所以你看到的就是这个。如果这就是您想要序列化和反序列化的内容,请在您的对象上调用 str() 成功了,谢谢。但是,我认为我犯了一个错误,就是将我正在处理的案例过于简单化了。通常,当我对 datetime.date 进行 jsonify 时,它是带有其他元素的 dict 的一部分,在这种情况下,这种方法不起作用。我更新了我的问题,以更好地展示我正在处理的案例。 【参考方案1】:

按照this snippet,您可以这样做:

from flask.json import JSONEncoder
from datetime import date


class CustomJSONEncoder(JSONEncoder):
    def default(self, obj):
        try:
            if isinstance(obj, date):
                return obj.isoformat()
            iterable = iter(obj)
        except TypeError:
            pass
        else:
            return list(iterable)
        return JSONEncoder.default(self, obj)

app = Flask(__name__)
app.json_encoder = CustomJSONEncoder

路线:

import datetime as dt

@app.route('/', methods=['GET'])
def index():
    now = dt.datetime.now()
    return jsonify('now': now)

【讨论】:

您能否详细说明与其他更简单的答案相比,try ... except ... else 块的必要性? @MaxNoe:在回顾更简单的方法时,我认为没有必要进行额外的检查,因为——如图所示——只需检查一个日期实例就可以了。感谢您的评论。【参考方案2】:

datetime.date 不是 JSON 类型,因此默认情况下不可序列化。相反,Flask 添加了一个钩子,将日期转储为 RFC 1123 格式的字符串,这与 HTTP 请求和响应的其他部分中的日期一致。

如果您想更改格式,请使用自定义 JSON 编码器。子类JSONEncoder 并将Flask.json_encoder 设置为它。

from flask import Flask
from flask.json import JSONEncoder

class MyJSONEncoder(JSONEncoder):
    def default(self, o):
        if isinstance(o, date):
            return o.isoformat()

        return super().default(o)

class MyFlask(Flask):
    json_encoder = MyJSONEncoder

app = MyFlask(__name__)

使用ISO 8601 传输和存储值是个好主意。它可以被 javascript Date.parse(和其他解析器)明确解析。输出时选择输出格式,而不是存储时选择。

表示 RFC 2822 或 ISO 8601 日期的字符串(可以使用其他格式,但结果可能出乎意料)。

当您加载数据时,无法知道该值是日期而不是字符串(因为日期不是 JSON 类型),因此您不会得到 datetime.date 回复,您会得到一个字符串。 (如果你确实有约会,它怎么知道返回 date 而不是 datetime?)

【讨论】:

【参考方案3】:

您可以更改your app's .json_encoder attribute,实现JSONEncoder 的变体,它可以根据您的需要设置日期格式。

【讨论】:

以上是关于使用 Flask 的 jsonify 时,将 datetime.date 保持为 'yyyy-mm-dd' 格式的主要内容,如果未能解决你的问题,请参考以下文章

防止 Flask jsonify 对数据进行排序

Flask jsonify 对象列表

Flask 中字典数据返回(jsonify)

jsonify Flask中的SQLAlchemy结果集[重复]

在flask中使用jsonify和json.dumps的区别

PyMongo 和 Flask 的 Jsonify 包含转义斜线