【问题标题】:Keep a datetime.date in 'yyyy-mm-dd' format when using Flask's jsonify使用 Flask 的 jsonify 时,将 datetime.date 保持为 'yyyy-mm-dd' 格式
【发布时间】:2017-09-25 14:08:43
【问题描述】:

由于某种原因,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

按照 cmets 中的建议,使用 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() 解决方案不起作用。

【问题讨论】:

  • 将其序列化为字符串?
  • 我不太明白你的意思。
  • jsonify(str(test_date))
  • 当你打印一个对象时,该对象的__str__方法被调用,所以你看到的就是这个。如果这就是您想要序列化和反序列化的内容,请在您的对象上调用 str()
  • 成功了,谢谢。但是,我认为我犯了一个错误,就是将我正在处理的案例过于简单化了。通常,当我对 datetime.date 进行 jsonify 时,它是带有其他元素的 dict 的一部分,在这种情况下,这种方法不起作用。我更新了我的问题,以更好地展示我正在处理的案例。

标签: python json date datetime flask


【解决方案1】:

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

【讨论】:

  • 您能否详细说明与其他更简单的答案相比,try ... except ... else 块的必要性?
  • @MaxNoe:在回顾更简单的方法时,我认为没有必要进行额外的检查,因为——如图所示——只需检查一个日期实例就可以了。感谢您的评论。
【解决方案2】:

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):
            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?)

【讨论】:

    【解决方案3】:

    您可以更改your app's .json_encoder attribute,实现JSONEncoder 的变体,它可以根据您的需要设置日期格式。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-01-19
      • 1970-01-01
      • 2021-12-18
      • 2023-03-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多