我有一个基本的词典如下:
sample = {}
sample['title'] = "String"
sample['somedate'] = somedatetimehere
Run Code Online (Sandbox Code Playgroud)
当我尝试做的时候,jsonify(sample)
我得到:
TypeError: datetime.datetime(2012, 8, 8, 21, 46, 24, 862000) is not JSON serializable
我能做些什么,以便我的字典样本可以克服上述错误?
注意:虽然它可能不相关,但字典是从mongodb中检索记录生成的,当我打印输出时str(sample['somedate'])
,输出是2012-08-08 21:46:24.862000
.
jjm*_*tes 479
我的快速和脏的JSON转储吃日期和所有东西:
json.dumps(my_dictionary, indent=4, sort_keys=True, default=str)
Run Code Online (Sandbox Code Playgroud)
jgb*_*rah 426
建立在其他答案的基础上,只是转换一个特定序列化一个简单的解决方案datetime.datetime
和datetime.date
对象为字符串.
from datetime import date, datetime
def json_serial(obj):
"""JSON serializer for objects not serializable by default json code"""
if isinstance(obj, (datetime, date)):
return obj.isoformat()
raise TypeError ("Type %s not serializable" % type(obj))
Run Code Online (Sandbox Code Playgroud)
如图所示,代码只是检查以确定对象是否为类datetime.datetime
或datetime.date
,然后.isoformat()
根据ISO 8601格式,YYYY-MM-DDTHH:MM:SS(可通过JavaScript轻松解码)用于生成它的序列化版本).如果寻求更复杂的序列化表示,可以使用其他代码而不是str()(例如,参见该问题的其他答案).代码以引发异常结束,以处理使用非可序列化类型调用的情况.
这个json_serial函数可以用如下:
from datetime import datetime
from json import dumps
print dumps(datetime.now(), default=json_serial)
Run Code Online (Sandbox Code Playgroud)
有关如何使用json.dumps的默认参数的详细信息,请参阅json模块文档的基本用法部分.
jdi*_*jdi 328
最初的答案符合MongoDB"date"字段的表示方式:
{"$date": 1506816000000}
如果你想要一个通用的Python解决方案来序列化为datetime
json,请查看@jjmontes的答案以获得一个不需要依赖的快速解决方案.
当您使用mongoengine(每条评论)并且pymongo是一个依赖项时,pymongo有内置的实用程序来帮助json序列化:http://api.mongodb.org/python/1.10.1/api/bson/json_util.html
用法示例(序列化):
from bson import json_util
import json
json.dumps(anObject, default=json_util.default)
Run Code Online (Sandbox Code Playgroud)
用法示例(反序列化):
json.loads(aJsonString, object_hook=json_util.object_hook)
Run Code Online (Sandbox Code Playgroud)
Django提供了一个DjangoJSONEncoder
处理这种正确的本机序列化程序.
请参阅https://docs.djangoproject.com/en/dev/topics/serialization/#djangojsonencoder
from django.core.serializers.json import DjangoJSONEncoder
return json.dumps(
item,
sort_keys=True,
indent=1,
cls=DjangoJSONEncoder
)
Run Code Online (Sandbox Code Playgroud)
我注意到DjangoJSONEncoder
和使用这样的自定义之间的一个区别default
:
import datetime
import json
def default(o):
if isinstance(o, (datetime.date, datetime.datetime)):
return o.isoformat()
return json.dumps(
item,
sort_keys=True,
indent=1,
default=default
)
Run Code Online (Sandbox Code Playgroud)
这是Django剥离了一些数据:
"last_login": "2018-08-03T10:51:42.990", # DjangoJSONEncoder
"last_login": "2018-08-03T10:51:42.990239", # default
Run Code Online (Sandbox Code Playgroud)
因此,在某些情况下,您可能需要小心.
小智 196
我刚遇到这个问题,我的解决方案是子类json.JSONEncoder
:
from datetime import datetime
import json
class DateTimeEncoder(json.JSONEncoder):
def default(self, o):
if isinstance(o, datetime):
return o.isoformat()
return json.JSONEncoder.default(self, o)
Run Code Online (Sandbox Code Playgroud)
在您的通话做这样的事情:json.dumps(yourobj, cls=DateTimeEncoder)
在.isoformat()
我从上面的答案之一了.
D.A*_*D.A 114
将日期转换为字符串
sample['somedate'] = str( datetime.utcnow() )
Run Code Online (Sandbox Code Playgroud)
Jay*_*lor 78
对于那些不需要或不想使用pymongo库的人来说,你可以使用这个小片段轻松实现datetime JSON转换:
def default(obj):
"""Default JSON serializer."""
import calendar, datetime
if isinstance(obj, datetime.datetime):
if obj.utcoffset() is not None:
obj = obj - obj.utcoffset()
millis = int(
calendar.timegm(obj.timetuple()) * 1000 +
obj.microsecond / 1000
)
return millis
raise TypeError('Not sure how to serialize %s' % (obj,))
Run Code Online (Sandbox Code Playgroud)
然后像这样使用它:
import datetime, json
print json.dumps(datetime.datetime.now(), default=default)
Run Code Online (Sandbox Code Playgroud)
输出:
'1365091796124'
Run Code Online (Sandbox Code Playgroud)
Nat*_*tim 37
这是我的解决方案:
# -*- coding: utf-8 -*-
import json
class DatetimeEncoder(json.JSONEncoder):
def default(self, obj):
try:
return super(DatetimeEncoder, obj).default(obj)
except TypeError:
return str(obj)
Run Code Online (Sandbox Code Playgroud)
然后你就可以这样使用它:
json.dumps(dictionnary, cls=DatetimeEncoder)
Run Code Online (Sandbox Code Playgroud)
cod*_*tty 20
我有一个类似问题的申请; 我的方法是将日期时间值JSONize为6项列表(年,月,日,小时,分钟,秒); 你可以将微秒作为一个7项目列表,但我没有必要:
class DateTimeEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, datetime.datetime):
encoded_object = list(obj.timetuple())[0:6]
else:
encoded_object =json.JSONEncoder.default(self, obj)
return encoded_object
sample = {}
sample['title'] = "String"
sample['somedate'] = datetime.datetime.now()
print sample
print json.dumps(sample, cls=DateTimeEncoder)
Run Code Online (Sandbox Code Playgroud)
生产:
{'somedate': datetime.datetime(2013, 8, 1, 16, 22, 45, 890000), 'title': 'String'}
{"somedate": [2013, 8, 1, 16, 22, 45], "title": "String"}
Run Code Online (Sandbox Code Playgroud)
fia*_*jaf 16
我的解决方案(我认为不那么冗长):
def default(o):
if type(o) is datetime.date or type(o) is datetime.datetime:
return o.isoformat()
def jsondumps(o):
return json.dumps(o, default=default)
Run Code Online (Sandbox Code Playgroud)
然后使用jsondumps
而不是json.dumps
.它将打印:
>>> jsondumps({'today': datetime.date.today()})
'{"today": "2013-07-30"}'
Run Code Online (Sandbox Code Playgroud)
我想要,稍后您可以通过简单的default
方法扭曲添加其他特殊情况.例:
def default(o):
if type(o) is datetime.date or type(o) is datetime.datetime:
return o.isoformat()
if type(o) is decimal.Decimal:
return float(o)
Run Code Online (Sandbox Code Playgroud)
dav*_*das 16
这个Q一次又一次地重复 - 一种修补json模块的简单方法,使序列化支持日期时间.
import json
import datetime
json.JSONEncoder.default = lambda self,obj: (obj.isoformat() if isinstance(obj, datetime.datetime) else None)
Run Code Online (Sandbox Code Playgroud)
比你经常使用json序列化 - 这次将datetime序列化为isoformat.
json.dumps({'created':datetime.datetime.now()})
Run Code Online (Sandbox Code Playgroud)
导致:'{"created":"2015-08-26T14:21:31.853855"}'
请参阅更多详细信息和注意事项: StackOverflow:Python和JavaScript之间的JSON日期时间
小智 10
这是一个简单的解决方案来解决"datetime not JSON serializable"问题.
enco = lambda obj: (
obj.isoformat()
if isinstance(obj, datetime.datetime)
or isinstance(obj, datetime.date)
else None
)
json.dumps({'date': datetime.datetime.now()}, default=enco)
Run Code Online (Sandbox Code Playgroud)
输出: - > {"date":"2015-12-16T04:48:20.024609"}
Ben*_*ari 10
您应该使用.strftime()
方法on .datetime.now()
将其作为可序列化方法.
这是一个例子:
from datetime import datetime
time_dict = {'time': datetime.now().strftime('%Y-%m-%dT%H:%M:%S')}
sample_dict = {'a': 1, 'b': 2}
sample_dict.update(time_dict)
sample_dict
Run Code Online (Sandbox Code Playgroud)
输出:
Out[0]: {'a': 1, 'b': 2, 'time': '2017-10-31T15:16:30'}
Run Code Online (Sandbox Code Playgroud)
Cyk*_*ker 10
如果您使用的是python3.7,那么最好的解决方案是使用
datetime.isoformat()
和
datetime.fromisoformat()
; 它们既可以用于天真datetime
对象,也可以用于感知对象:
#!/usr/bin/env python3.7
from datetime import datetime
from datetime import timezone
from datetime import timedelta
import json
def default(obj):
if isinstance(obj, datetime):
return { '_isoformat': obj.isoformat() }
return super().default(obj)
def object_hook(obj):
_isoformat = obj.get('_isoformat')
if _isoformat is not None:
return datetime.fromisoformat(_isoformat)
return obj
if __name__ == '__main__':
#d = { 'now': datetime(2000, 1, 1) }
d = { 'now': datetime(2000, 1, 1, tzinfo=timezone(timedelta(hours=-8))) }
s = json.dumps(d, default=default)
print(s)
print(d == json.loads(s, object_hook=object_hook))
Run Code Online (Sandbox Code Playgroud)
输出:
{"now": {"_isoformat": "2000-01-01T00:00:00-08:00"}}
True
Run Code Online (Sandbox Code Playgroud)
如果您使用的是python3.6或更低版本,并且您仅关心时间值(而不是时区),则可以使用datetime.timestamp()
和
datetime.fromtimestamp()
;
如果您使用的是python3.6或更低版本,并且确实关心时区,则可以通过进行获取datetime.tzinfo
,但是您必须自己序列化此字段;最简单的方法是_tzinfo
在序列化对象中添加另一个字段;
最后,在所有这些示例中都要当心精度;
json.dumps方法可以接受称为default的可选参数,该参数应为函数。每次JSON尝试转换值时,它都不知道如何转换将调用我们传递给它的函数。该函数将接收有问题的对象,并且应返回该对象的JSON表示形式。
def myconverter(o):
if isinstance(o, datetime.datetime):
return o.__str__()
print(json.dumps(d, default = myconverter))
Run Code Online (Sandbox Code Playgroud)
您必须提供cls
参数为的自定义编码器类json.dumps
.引用文档:
>>> import json
>>> class ComplexEncoder(json.JSONEncoder):
... def default(self, obj):
... if isinstance(obj, complex):
... return [obj.real, obj.imag]
... return json.JSONEncoder.default(self, obj)
...
>>> dumps(2 + 1j, cls=ComplexEncoder)
'[2.0, 1.0]'
>>> ComplexEncoder().encode(2 + 1j)
'[2.0, 1.0]'
>>> list(ComplexEncoder().iterencode(2 + 1j))
['[', '2.0', ', ', '1.0', ']']
Run Code Online (Sandbox Code Playgroud)
这使用复数作为示例,但您可以轻松创建一个类来编码日期(除了我认为JSON对日期有点模糊)
我通常使用orjson
. 不仅因为其出色的性能,还因为其出色的(符合 RFC-3339 )支持datetime
:
import orjson # via pip3 install orjson
from datetime import datetime
data = {"created_at": datetime(2022, 3, 1)}
orjson.dumps(data) # returns b'{"created_at":"2022-03-01T00:00:00"}'
Run Code Online (Sandbox Code Playgroud)
如果您想使用datetime.datetime
没有 tzinfo 的对象作为 UTC,您可以添加相关选项:
orjson.dumps(data, option=orjson.OPT_NAIVE_UTC) # returns b'{"created_at":"2022-03-01T00:00:00+00:00"}'
Run Code Online (Sandbox Code Playgroud)
用一个例子试试这个来解析它:
#!/usr/bin/env python
import datetime
import json
import dateutil.parser # pip install python-dateutil
class JSONEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, datetime.datetime):
return obj.isoformat()
return super(JSONEncoder, self).default(obj)
def test():
dts = [
datetime.datetime.now(),
datetime.datetime.now(datetime.timezone(-datetime.timedelta(hours=4))),
datetime.datetime.utcnow(),
datetime.datetime.now(datetime.timezone.utc),
]
for dt in dts:
dt_isoformat = json.loads(json.dumps(dt, cls=JSONEncoder))
dt_parsed = dateutil.parser.parse(dt_isoformat)
assert dt == dt_parsed
print(f'{dt}, {dt_isoformat}, {dt_parsed}')
# 2018-07-22 02:22:42.910637, 2018-07-22T02:22:42.910637, 2018-07-22 02:22:42.910637
# 2018-07-22 02:22:42.910643-04:00, 2018-07-22T02:22:42.910643-04:00, 2018-07-22 02:22:42.910643-04:00
# 2018-07-22 06:22:42.910645, 2018-07-22T06:22:42.910645, 2018-07-22 06:22:42.910645
# 2018-07-22 06:22:42.910646+00:00, 2018-07-22T06:22:42.910646+00:00, 2018-07-22 06:22:42.910646+00:00
if __name__ == '__main__':
test()
Run Code Online (Sandbox Code Playgroud)
其实很简单。如果您需要经常序列化日期,请将它们作为字符串使用。如果需要,您可以轻松地将它们转换回日期时间对象。
如果您需要主要作为日期时间对象工作,那么在序列化之前将它们转换为字符串。
import json, datetime
date = str(datetime.datetime.now())
print(json.dumps(date))
"2018-12-01 15:44:34.409085"
print(type(date))
<class 'str'>
datetime_obj = datetime.datetime.strptime(date, '%Y-%m-%d %H:%M:%S.%f')
print(datetime_obj)
2018-12-01 15:44:34.409085
print(type(datetime_obj))
<class 'datetime.datetime'>
Run Code Online (Sandbox Code Playgroud)
如您所见,两种情况下的输出是相同的。只是类型不同。
最简单的方法是将日期时间格式的dict部分更改为isoformat.该值实际上是isoformat中的一个字符串,json可以使用.
v_dict = version.dict()
v_dict['created_at'] = v_dict['created_at'].isoformat()
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
442855 次 |
最近记录: |