Почему 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__
то есть способ упорядочения уже доступного объекта, но кажется сознательным решением не делать этого, почему это так?
4 ответа
Нет, это не работает таким образом в 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 не определяет, как можно представить дату и время.
Как бы вы хотели, чтобы они были сериализованы?
JSON не определяет, как обрабатывать даты, поэтому Python json
библиотека не может принять решение о том, как затем представлять их для вас. Это полностью зависит от того, как другая сторона (браузер, скрипт, что угодно) также обрабатывает даты в JSON.
Простой способ залатать модуль 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()})
В результате: '{"созданный": "2015-08-26T14:21:31.853855"}'
Более подробную информацию и несколько слов предостережения смотрите по адресу: Stackru: JSON datetime между Python и JavaScript
Если вы хотите получить кодирование и декодирование datetime без необходимости его реализации, вы можете использовать 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)
Но обратите внимание, что у этого есть недостатки, например, ни один из них не будет десериализован без дополнительных усилий, и, возможно, иногда вы просто не хотите сериализовать что-то (например, функцию большого массива с нулевыми значениями), но вместо этого получите предупреждение, которое этот метод будет молчание.