关于python:使用Flask的jsonify时,将datetime.date保持为’yyyy-mm-dd’格式

Keep a datetime.date in 'yyyy-mm-dd' format when using Flask's jsonify

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

1
2
3
4
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

正如评论中所建议的那样,使用jsonify(str(test_date))返回所需的格式。 但是,请考虑以下情况:

1
2
3
4
5
6
7
8
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()解决方案不起作用。


在此片段之后,您可以执行以下操作:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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

路线:

1
2
3
4
5
6
import datetime as dt

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

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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(和其他解析器)明确地解析。输出时选择输出格式,而不是存储时。

A string representing an RFC 2822 or ISO 8601 date (other formats may be used, but results may be unexpected).

当你加载数据时,没有办法知道该值是一个日期而不是一个字符串(因为日期不是一个JSON类型),所以你没有得到datetime.date,你得到一个字符串。 (如果你确实得到了约会,那么如何知道返回date而不是datetime?)


您可以更改应用的.json_encoder属性,实现JSONEncoder的变体,根据您的需要格式化日期。