datetime.date(2014, 4, 25) 在Django中无法序列化为JSON
编辑
这个问题并不是重复的,和“如何解决‘datetime.datetime 不能被 JSON 序列化’?”不一样。虽然它们是同样的问题,但这个问题有特定的背景:Django。因此,有些解决方案在这里适用,而在那个链接的问题中则不适用。
原始问题
我按照“如何解决‘datetime.datetime 不能被 JSON 序列化’?”的内容去做,但这对我没有帮助。
我尝试了这段代码
>>> import datetime
>>> a =datetime.date(2014, 4, 25)
>>> from bson import json_util
>>> b = json.dumps(a,default = json_util.default)
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "/usr/lib/python2.7/json/__init__.py", line 250, in dumps
sort_keys=sort_keys, **kw).encode(obj)
File "/usr/lib/python2.7/json/encoder.py", line 207, in encode
chunks = self.iterencode(o, _one_shot=True)
File "/usr/lib/python2.7/json/encoder.py", line 270, in iterencode
return _iterencode(o, 0)
File "/home/.../python2.7/site-packages/bson/json_util.py", line 256, in default
raise TypeError("%r is not JSON serializable" % obj)
TypeError: datetime.date(2014, 4, 25) is not JSON serializable
有人能帮我写一个datetime.date
的序列化和反序列化的代码吗?
5 个回答
2
我发现这个非常有用,特别是在把Django从1.7更新到1.9之后。大部分内容来自这个博客 http://arthurpemberton.com/2015/04/fixing-uuid-is-not-json-serializable。把这个放在models.py文件中,紧跟在导入部分下面。这样就能帮你处理UUID的问题了。
from uuid import UUID
import datetime
JSONEncoder_olddefault = JSONEncoder.default
def JSONEncoder_newdefault(self, o):
if isinstance(o, UUID): return str(o)
if isinstance(o, datetime.datetime): return str(o)
return JSONEncoder_olddefault(self, o)
JSONEncoder.default = JSONEncoder_newdefault
7
在处理模型查询集的时候,你可以在JSON的跳转功能里加入一个日期时间编码器。这是经过一些调整的,因为我在解析基础的Django模型状态时遇到了一些问题。
import datetime
import decimal
from django.db.models.base import ModelState
class DateTimeEncoder(json.JSONEncoder):
def default(self, obj):
if hasattr(obj, 'isoformat'):
return obj.isoformat()
elif isinstance(obj, decimal.Decimal):
return float(obj)
elif isinstance(obj, ModelState):
return None
else:
return json.JSONEncoder.default(self, obj)
然后,使用这个类来处理你的json数据。
b = json.dumps(a, cls = DateTimeEncoder)
10
请查看json包文档中的扩展编码器部分 https://docs.python.org/2/library/json.html
我用过这个方法,觉得效果很好。我觉得这正是你需要的。
import json
class DatetimeEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, datetime):
return obj.strftime('%Y-%m-%dT%H:%M:%SZ')
elif isinstance(obj, date):
return obj.strftime('%Y-%m-%d')
# Let the base class default method raise the TypeError
return json.JSONEncoder.default(self, obj)
json.dumps(dict,cls=DatetimeEncoder)
14
将日期转换为等效的ISO格式,
In [29]: datetime.datetime.now().isoformat()
Out[29]: '2020-03-06T12:18:54.114600'
64
你也可以这样做:
def date_handler(obj):
return obj.isoformat() if hasattr(obj, 'isoformat') else obj
print json.dumps(data, default=date_handler)
来自 这里。
更新 根据 J.F.Sebastian 的评论
def date_handler(obj):
if hasattr(obj, 'isoformat'):
return obj.isoformat()
else:
raise TypeError
print json.dumps(data, default=date_handler)