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

610   4  

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 таким образом, чтобы сериализация поддерживала datetime.

import json
import datetime

json.JSONEncoder.default = lambda self,obj: (obj.isoformat() if isinstance(obj, datetime.datetime) else None)

Чем использовать сериализацию json, как вы всегда делаете - на этот раз с сериализацией datetime в виде изоформата.

json.dumps({'created':datetime.datetime.now()})

В результате чего: '{"создано": "2015-08-26T14:21:31.853855"}'

Подробнее и несколько слов предостережения см.: StackOverflow: JSON datetime между Python и JavaScript

Если вы хотите получить кодирование и декодирование временных интервалов без необходимости его реализации, вы можете использовать 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), но вместо этого получите предупреждение, которое этот метод заставит замолчать.

Comments

    Ничего не найдено.