web-dev-qa-db-ja.com

Flaskのjsonifyを使用する場合、datetime.dateを「yyyy-mm-dd」形式で保持します

何らかの理由で、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
_

コメントで提案されているように、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()ソリューションは機能しません。

17
nessus_pp

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

datetime.dateはJSONタイプではないため、デフォルトではシリアル化できません。代わりに、Flaskは、日付を RFC 112 形式で文字列にダンプするフックを追加します。これは、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を返すことがどのようにしてわかりますか?)

14
davidism

変更できます アプリの.json_encoder属性JSONEncoder のバリアントを実装して、日付を適切にフォーマットします。

1
9000