Как обойти "datetime.datetime не сериализуем в JSON"?
У меня есть основной словарь, который выглядит следующим образом:
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 ответ(ов)
Ваш быстрый и неаккуратный JSON-дамп, который обрабатывает даты и всё остальное:
json.dumps(my_dictionary, indent=4, sort_keys=True, default=str)
Параметр
default
— это функция, которая применяется к объектам, не поддающимся сериализации. В данном случае указана функцияstr
, поэтому всё, что не может быть сериализовано, просто преобразуется в строки. Это отлично подходит для сериализации, но не очень хорошо для десериализации (поэтому "быстро и неаккуратно"), так как что угодно могло быть преобразовано в строку без предупреждения, например, функция или массив NumPy.
Если вы столкнулись с проблемой сериализации объектов 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.
Чтобы преобразовать дату в строку в 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()
придает вам больше контроля над форматом.
Для тех, кто не нуждается и не хочет использовать библиотеку 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'
Вот моё решение:
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 будут обработаны и неподдерживаемые типы.
Почему Python не может разобрать эти данные JSON? [закрыто]
Как записать данные JSON в файл?
Как сделать класс сериализуемым в JSON
Как отправить JSON-данные с помощью Python Requests?
Как отсортировать список/кортеж списков/кортежей по элементу на заданном индексе