如何克服“ datetime.datetime无法JSON序列化”?

本文翻译自:How to overcome “datetime.datetime not JSON serializable”?

I have a basic dict as follows: 我有一个基本的命令,如下所示:

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

When I try to do jsonify(sample) I get: 当我尝试执行jsonify(sample)我得到:

TypeError: datetime.datetime(2012, 8, 8, 21, 46, 24, 862000) is not JSON serializable

What can I do such that my dictionary sample can overcome the error above? 我该怎么做才能使我的词典示例可以克服上述错误?

Note: Though it may not be relevant, the dictionaries are generated from the retrieval of records out of mongodb where when I print out str(sample['somedate']) , the output is 2012-08-08 21:46:24.862000 . 注意:尽管可能不相关,但字典是从mongodb中检索记录生成的,当我打印出str(sample['somedate']) ,输出为2012-08-08 21:46:24.862000


#1楼

参考:https://stackoom.com/question/npQg/如何克服-datetime-datetime无法JSON序列化


#2楼

Updated for 2018 更新于2018

The original answer accommodated the way MongoDB "date" fields were represented as: 原始答案适应了MongoDB“日期”字段表示为:

{"$date": 1506816000000}

If you want a generic Python solution for serializing datetime to json, check out @jjmontes' answer for a quick solution which requires no dependencies. 如果您想要将datetime时间序列化为json的通用Python解决方案,请查看@jjmontes的答案以获取无需依赖项的快速解决方案。


As you are using mongoengine (per comments) and pymongo is a dependency, pymongo has built-in utilities to help with json serialization: 当您使用mongoengine(每个注释)并且pymongo是一个依赖项时,pymongo具有内置的实用程序来帮助json序列化:
http://api.mongodb.org/python/1.10.1/api/bson/json_util.html http://api.mongodb.org/python/1.10.1/api/bson/json_util.html

Example usage (serialization): 用法示例(序列化):

from bson import json_util
import json

json.dumps(anObject, default=json_util.default)

Example usage (deserialization): 用法示例(反序列化):

json.loads(aJsonString, object_hook=json_util.object_hook)

Django Django的

Django provides a native DjangoJSONEncoder serializer that deals with this kind of properly. Django提供了本机DjangoJSONEncoder序列化程序,可以正确处理这种情况。

See https://docs.djangoproject.com/en/dev/topics/serialization/#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
)

One difference I've noticed between DjangoJSONEncoder and using a custom default like this: 我注意到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
)

Is that Django strips a bit of the data: 是Django剥离了一些数据:

 "last_login": "2018-08-03T10:51:42.990", # DjangoJSONEncoder 
 "last_login": "2018-08-03T10:51:42.990239", # default

So, you may need to be careful about that in some cases. 因此,在某些情况下,您可能需要注意这一点。


#3楼

将日期转换为字符串

sample['somedate'] = str( datetime.utcnow() )

#4楼

You have to supply a custom encoder class with the cls parameter of json.dumps . 您必须提供一个带有json.dumpscls参数的自定义编码器类。 To quote from the docs : 引用文档

>>> 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', ']']

This uses complex numbers as the example, but you can just as easily create a class to encode dates (except I think JSON is a little fuzzy about dates) 这以复数为例,但是您可以轻松地创建一个类来对日期进行编码(但我认为JSON对日期有些模糊)


#5楼

For others who do not need or want to use the pymongo library for this.. you can achieve datetime JSON conversion easily with this small snippet: 对于不需要或想要使用pymongo库的其他人,您可以使用此小片段轻松实现日期时间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,))

Then use it like so: 然后像这样使用它:

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

output: 输出:

'1365091796124'

#6楼

Here is my solution: 这是我的解决方案:

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

Then you can use it like that: 然后,您可以像这样使用它:

json.dumps(dictionnary, cls=DatetimeEncoder)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值