我有一个基本的字典如下:

sample = {}
sample['title'] = "String"
sample['somedate'] = somedatetimehere

当我尝试做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。


当前回答

我有一个类似问题的应用程序;我的方法是将datetime值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)

生产:

{'somedate': datetime.datetime(2013, 8, 1, 16, 22, 45, 890000), 'title': 'String'}
{"somedate": [2013, 8, 1, 16, 22, 45], "title": "String"}

其他回答

如果你正在使用django模型,你可以直接将encoder=DjangoJSONEncoder传递给field构造函数。它会像魔法一样有效。

from django.core.serializers.json import DjangoJSONEncoder 
from django.db import models 
from django.utils.timezone import now


class Activity(models.Model):
    diff = models.JSONField(null=True, blank=True, encoder=DjangoJSONEncoder)


diff = {
    "a": 1,
    "b": "BB",
    "c": now()
}

Activity.objects.create(diff=diff)

在其他答案的基础上,一个简单的解决方案基于只转换datetime的特定序列化器。Datetime和Datetime。将对象日期指定为字符串。

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

As seen, the code just checks to find out if object is of class datetime.datetime or datetime.date, and then uses .isoformat() to produce a serialized version of it, according to ISO 8601 format, YYYY-MM-DDTHH:MM:SS (which is easily decoded by JavaScript). If more complex serialized representations are sought, other code could be used instead of str() (see other answers to this question for examples). The code ends by raising an exception, to deal with the case it is called with a non-serializable type.

这个json_serial函数可以这样使用:

from datetime import datetime
from json import dumps

print dumps(datetime.now(), default=json_serial)

详细说明如何将默认参数设置为json。可以在json模块文档的基本用法章节中找到dump作品。

如果你想要自己的格式,一个快速修复

for key,val in sample.items():
    if isinstance(val, datetime):
        sample[key] = '{:%Y-%m-%d %H:%M:%S}'.format(val) #you can add different formating here
json.dumps(sample)
def j_serial(o):     # self contained
    from datetime import datetime, date
    return str(o).split('.')[0] if isinstance(o, (datetime, date)) else None

以上用途的使用:

import datetime
serial_d = j_serial(datetime.datetime.now())
if serial_d:
    print(serial_d)  # output: 2018-02-28 02:23:15

对于不需要或不想使用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,))

然后像这样使用它:

import datetime, json
print json.dumps(datetime.datetime.now(), default=default)

输出:

'1365091796124'