web-dev-qa-db-fra.com

Conserver un datetime.date au format 'aaaa-mm-jj' lors de l'utilisation de jsonify de Flask

Pour une raison quelconque, la fonction jsonify convertit mon datetime.date En ce qui semble être une date HTTP. Comment puis-je conserver la date au format yyyy-mm-dd Lorsque j'utilise 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

Comme suggéré dans les commentaires, l'utilisation de jsonify(str(test_date)) renvoie le format souhaité. Cependant, considérez le cas suivant:

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

Dans ce cas, la solution str() ne fonctionne pas.

17
nessus_pp

Après cet extrait vous pouvez le faire:

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

Route:

import datetime as dt

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

datetime.date n'est pas un type JSON, il n'est donc pas sérialisable par défaut. Au lieu de cela, Flask ajoute un crochet pour vider la date dans une chaîne au format RFC 112 , ce qui est cohérent avec les dates dans d'autres parties des requêtes et réponses HTTP.

Utilisez un encodeur JSON personnalisé si vous souhaitez modifier le format. Sous-classe JSONEncoder et définissez 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__)

C'est une bonne idée d'utiliser ISO 8601 pour transmettre et stocker la valeur. Il peut être analysé sans ambiguïté par JavaScript Date.parse (et autres analyseurs). Choisissez le format de sortie lorsque vous sortez, pas lorsque vous stockez.

Une chaîne représentant une date RFC 2822 ou ISO 8601 (d'autres formats peuvent être utilisés, mais les résultats peuvent être inattendus).

Lorsque vous chargez les données, il n'y a aucun moyen de savoir que la valeur était censée être une date au lieu d'une chaîne (puisque la date n'est pas un type JSON), donc vous n'obtenez pas de datetime.date retour, vous obtenez une chaîne. (Et si vous aviez une date, comment saurait-elle retourner date au lieu de datetime?)

14
davidism

Vous pouvez modifier l'attribut .json_encoder De votre application , en implémentant une variante de JSONEncoder qui formate les dates comme bon vous semble.

1
9000