Search code examples
pythonjsondatedatetimeflask

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


For some reason, the jsonify function is converting my datetime.date to what appears to be an HTTP date. How can I keep the date in yyyy-mm-dd format when using 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

As suggested in the comments, using jsonify(str(test_date)) returns the desired format. However, consider the following case:

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

In this case, the str() solution does not work.


Solution

  • edit: this answer is now too old for Flask versions 2.3+.

    for those newer versions, instead customize json_provider_class; reference: https://flask.palletsprojects.com/en/2.2.x/api/?highlight=json_encoder#flask.Flask.json_provider_class


    Following this snippet you can do this:

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