Почему json-сериализация объектов datetime в python не работает из коробки для объектов datetime
Почему сериализация json не работает для объектов datetime. Поскольку я понимаю сериализацию json, основная идея для любого объекта может быть вызвана встроенной функцией __str__
, а затем urlencode объект, который вы получаете как ответ. Но в случае datetime я получаю следующую ошибку:
TypeError: datetime.datetime(2012, 5, 23, 18, 38, 23, 37566) is not JSON serializable
в то время как существует __str__
i.e способ создания объекта, который уже доступен, но кажется, что это сознательное решение не делать этого, почему бы так?
Ответы
Ответ 1
Нет, это не работает в модуле json
. Модуль предоставляет вам кодер по умолчанию: json.JSONEncoder
. Вы должны расширить это, чтобы обеспечить реализацию метода default
для сериализации объектов. Что-то вроде этого:
import json
import datetime
from time import mktime
class MyEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, datetime.datetime):
return int(mktime(obj.timetuple()))
return json.JSONEncoder.default(self, obj)
print json.dumps(obj, cls=MyEncoder)
Как правильно указали другие, причина в том, что стандарт для json не указывает, как можно представить дату.
Ответ 2
Как бы вы хотели, чтобы они были сериализованы?
JSON не указывает, как обрабатывать даты, поэтому библиотека python json
не может принять решение о том, как затем представить их для вас. Это полностью зависит от того, как другая сторона (браузер, script, независимо) обрабатывает даты в JSON.
Ответ 3
Простой способ исправления json-модуля таким образом, чтобы сериализация поддерживала дату и время.
import json
import datetime
json.JSONEncoder.default = lambda self,obj: (obj.isoformat() if isinstance(obj, datetime.datetime) else None)
Вместо использования сериализации json, как вы всегда это делаете, на этот раз с datetime, который сериализуется как isoformat.
json.dumps({'created':datetime.datetime.now()})
В результате: '{ "created": "2015-08-26T14: 21: 31.853855" }'
См. более подробную информацию и некоторые предостережения:
fooobar.com/questions/7691/...
Ответ 4
Если вы хотите получить кодирование и декодирование данных, не выполняя его, вы можете использовать json_tricks, который является оберткой, которая добавляет кодировку и декодирование для различных популярных типов. Просто установите:
pip install json_tricks
а затем импортируйте из json_tricks
вместо json
, например:
from json_tricks import dumps, loads
json = dumps({'name': 'MyName', 'birthday': datetime.datetime(1992, 5, 23, 18, 38, 23, 37566)})
me = loads(json)
Отказ от ответственности: это сделано мной. Потому что у меня была такая же проблема.
Если вы хотите автоматически сериализовать что-либо, что может быть сжато, вы можете сделать это с помощью стандартной реализации очень легко:
dumps(obj, default=str)
Но обратите внимание, что это имеет недостатки, например. ни один из них не будет десериализован без дополнительных усилий, и, возможно, иногда вы просто не хотите сериализовать что-либо (например, функцию большого массива numpy), но вместо этого получите предупреждение, которое будет отключено этим методом.