Подтвердить что ты не робот

Почему 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 способ создания объекта, который уже доступен, но кажется, что это сознательное решение не делать этого, почему бы так?

4b9b3361

Ответ 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), но вместо этого получите предупреждение, которое будет отключено этим методом.