14

Как обойти "datetime.datetime не сериализуем в JSON"?

12

У меня есть основной словарь, который выглядит следующим образом:

sample = {}
sample['title'] = "String"
sample['somedate'] = somedatetimehere

Когда я пытаюсь выполнить jsonify(sample), я получаю следующую ошибку:

TypeError: datetime.datetime(2012, 8, 8, 21, 46, 24, 862000) is not JSON serializable

Что я могу сделать, чтобы мой словарь sample смог преодолеть указанную ошибку?

Примечание: Хотя это может быть несущественно, словари генераируются из получения записей из mongodb, и когда я вывожу str(sample['somedate']), результатом является 2012-08-08 21:46:24.862000.

5 ответ(ов)

17

Ваш быстрый и неаккуратный JSON-дамп, который обрабатывает даты и всё остальное:

json.dumps(my_dictionary, indent=4, sort_keys=True, default=str)

Параметр default — это функция, которая применяется к объектам, не поддающимся сериализации. В данном случае указана функция str, поэтому всё, что не может быть сериализовано, просто преобразуется в строки. Это отлично подходит для сериализации, но не очень хорошо для десериализации (поэтому "быстро и неаккуратно"), так как что угодно могло быть преобразовано в строку без предупреждения, например, функция или массив NumPy.

3

Если вы столкнулись с проблемой сериализации объектов datetime в JSON, вы можете воспользоваться подклассом json.JSONEncoder. Вот пример решения:

from datetime import datetime
import json

class DateTimeEncoder(json.JSONEncoder):
    def default(self, o):
        if isinstance(o, datetime):
            return o.isoformat()
        return super().default(o)

Теперь, чтобы сериализовать ваш объект, используйте вызов json.dumps следующим образом:

json_string = json.dumps(yourobj, cls=DateTimeEncoder)

Метод .isoformat(), который мы используем для преобразования объектов datetime в строку, был получен из одного из предыдущих ответов. Такое решение позволяет корректно сериализовать объекты datetime в формат, понятный для JSON.

1

Чтобы преобразовать дату в строку в Python, вы можете использовать метод str() или метод strftime() для более форматированного вывода. Вот простой пример, как это сделать с помощью datetime из модуля datetime:

from datetime import datetime

# Получаем текущую дату и время в UTC
current_datetime = datetime.utcnow()

# Преобразуем его в строку
sample['somedate'] = current_datetime.strftime('%Y-%m-%d %H:%M:%S')

В этом примере strftime('%Y-%m-%d %H:%M:%S') позволяет вам указать формат, в котором вы хотите получить строковое представление даты и времени. Если вас устраивает просто строковое преобразование, то использование str(current_datetime) также подойдет:

sample['somedate'] = str(current_datetime)

Этот метод отобразит дату и время по умолчанию, но использование strftime() придает вам больше контроля над форматом.

0

Для тех, кто не нуждается и не хочет использовать библиотеку pymongo для этого, вы можете легко добиться конвертации datetime в JSON с помощью следующего небольшого кода:

def default(obj):
    """Стандартный сериализатор JSON."""
    import calendar, datetime

    if isinstance(obj, datetime.datetime):
        if obj.utcoffset() is not None:
            obj = obj - obj.utcoffset()
        millis = int(
            calendar.timegm(obj.timetuple()) * 1000 +
            obj.microsecond / 1000
        )
        return millis
    raise TypeError('Не знаю, как сериализовать %s' % (obj,))

Затем вы можете использовать его следующим образом:

import datetime, json
print(json.dumps(datetime.datetime.now(), default=default))

На выходе вы получите:

'1365091796124'
0

Вот моё решение:

import json

class DatetimeEncoder(json.JSONEncoder):
    def default(self, obj):
        try:
            return super().default(obj)
        except TypeError:
            return str(obj)

Теперь вы можете использовать его следующим образом:

json.dumps(dictionary, cls=DatetimeEncoder)

Таким образом, при сериализации объектов в JSON будут обработаны и неподдерживаемые типы.

Чтобы ответить на вопрос, пожалуйста, войдите или зарегистрируйтесь