Храните datetime.date в формате «yyyy-mm-dd» при использовании jsonify Flask

По какой-то причине функция jsonify преобразует мой datetime.date в то, что кажется датой HTTP. Как сохранить дату в формате yyyy-mm-dd при использовании jsonify ?

 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)) возвращает желаемый формат. Однако рассмотрим следующий случай:

 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() не работает.

Следуя этому фрагменту, вы можете сделать это:

 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}) 

Вы можете изменить атрибут .json_encoder вашего приложения , реализуя вариант JSONEncoder который форматирует даты по своему усмотрению.

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): # you said you want o.strftime('%Y-%m-%d'), but see below return o.isoformat() return super().default(o) class MyFlask(Flask): json_encoder = MyJSONEncoder app = MyFlask(__name__) 

Рекомендуется использовать ISO 8601 вместо YYYY-mm-dd. Его можно однозначно анализировать с помощью JavaScript Date.parse (и других парсеров).

Строка, представляющая дату RFC2822 или ISO 8601 (могут использоваться другие форматы, но результаты могут быть неожиданными).

Когда вы загружаете данные, нет способа узнать, что значение должно означать дату вместо строки (поскольку дата не является типом JSON), поэтому вы не получите datetime.date назад, вы получите строку. (И если вы получили дату, как бы знать, как вернуть date вместо datetime ?)