Почему 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)

Но обратите внимание, что у этого есть недостатки, например, ни один из них не будет десериализован без дополнительных усилий, и, возможно, иногда вы просто не хотите сериализовать что-то (например, функцию большого массива с нулевыми значениями), но вместо этого получите предупреждение, которое этот метод будет молчание.

Другие вопросы по тегам