使用 Flask 的 jsonify 时,将 datetime.date 保持为 'yyyy-mm-dd' 格式
Posted
技术标签:
【中文标题】使用 Flask 的 jsonify 时,将 datetime.date 保持为 \'yyyy-mm-dd\' 格式【英文标题】: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 的一部分,在这种情况下,这种方法不起作用。我更新了我的问题,以更好地展示我正在处理的案例。
【参考方案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
的变体,它可以根据您的需要设置日期格式。
【讨论】:
以上是关于使用 Flask 的 jsonify 时,将 datetime.date 保持为 'yyyy-mm-dd' 格式的主要内容,如果未能解决你的问题,请参考以下文章
jsonify Flask中的SQLAlchemy结果集[重复]