У меня есть основные слова:
sample = {}
sample['title'] = "String"
sample['somedate'] = somedatetimehere
Когда я пытаюсь сделать jsonify(sample)
я получаю:
TypeError: datetime.datetime(2012, 8, 8, 21, 46, 24, 862000) is not JSON serializable
Что я могу сделать, чтобы мой пример словаря смог преодолеть ошибку, описанную выше?
Примечание. Хотя это может быть неактуально, словари создаются на основе поиска записей, из mongodb
которых, когда я распечатываю str(sample['somedate'])
, вывод получается 2012-08-08 21:46:24.862000
.
Ответы:
Обновлено для 2018
Исходный ответ соответствовал тому, как поля даты в MongoDB были представлены как:
{"$date": 1506816000000}
Если вы хотите универсальное решение Python для сериализации
datetime
в json, посмотрите ответ @jjmontes для быстрого решения, которое не требует никаких зависимостей.Поскольку вы используете mongoengine (для комментариев), а pymongo является зависимостью, pymongo имеет встроенные утилиты, помогающие с сериализацией json:
http://api.mongodb.org/python/1.10.1/api/bson/json_util.html
Пример использования (сериализация):
Пример использования (десериализация):
Джанго
Джанго обеспечивает родной
DjangoJSONEncoder
сериализатор, который правильно обрабатывает этот вид.См. Https://docs.djangoproject.com/en/dev/topics/serialization/#djangojsonencoder.
Одно отличие, которое я заметил между
DjangoJSONEncoder
и использованием кастомовdefault
вроде этого:Это Django отбирает немного данных:
Таким образом, в некоторых случаях вам может потребоваться быть осторожным с этим.
источник
Django MongoDB
. В последнем случае вы пытаетесь оставаться в рамках django ORM, чтобы поддерживать независимое состояние бэкенда. Но иногда вы не можете делать то, что вам нужно в абстракции, поэтому вы опускаете слой. В этом случае это совершенно не связано с вашей проблемой, поскольку вы просто используете служебные методы для сопровождения формата JSON.Мой быстрый и грязный дамп JSON, который ест даты и все:
источник
default
это функция, применяемая к объектам, которые не сериализуются. В этом случае онstr
просто конвертирует все, что он не знает, в строки. Который отлично подходит для сериализации, но не настолько хорош при десериализации (отсюда и «быстрая и грязная»), так как все может быть строкой без предупреждения, например, функция или массив элементов.json.dumps({():1,type(None):2},default=str)
поднимаетTypeError
, не может иметь тип или кортеж.Опираясь на другие ответы, простое решение , основанное на определенном сериализатором , что только новообращенные
datetime.datetime
иdatetime.date
объекты в строки.Как видно, код просто проверяет, является ли объект классом
datetime.datetime
илиdatetime.date
, а затем использует его.isoformat()
для создания его сериализованной версии в соответствии с форматом ISO 8601, YYYY-MM-DDTHH: MM: SS (который легко декодируется с помощью JavaScript ). Если искать более сложные сериализованные представления, можно использовать другой код вместо str () (см. Другие ответы на этот вопрос для примеров). Код заканчивается созданием исключения, чтобы иметь дело с случаем, когда он вызывается с несериализуемым типом.Эта функция json_serial может использоваться следующим образом:
Подробную информацию о том, как работает параметр по умолчанию для json.dumps, можно найти в разделе «Основное использование» документации модуля json .
источник
01:00:00+01:00
и02:00:00+00:00
не должно быть одинаковым, в зависимости от контекста. Конечно, они ссылаются на один и тот же момент времени, но смещение может быть важным аспектом значения.Я только что столкнулся с этой проблемой, и мое решение заключается в подклассе
json.JSONEncoder
:В вашем вызове сделать что - то вроде:
json.dumps(yourobj, cls=DateTimeEncoder)
The.isoformat()
я получил от одного из вышеуказанных ответов.источник
DjangoJSONEncoder
. docs.djangoproject.com/en/dev/topics/serialization/…return super(DateTimeEncoder, self).default(o)
return super().default(o)
Преобразовать дату в строку
источник
oDate = datetime.datetime.strptime(sDate, '%Y-%m-%d %H:%M:%S.%f')
. Форматы получены из: docs.python.org/2/library/datetime.html.now()
использует местное время, не указывая этого. По крайней мере,.utcnow()
следует использовать (а затем добавить +0000 или Z)At least .utcnow() should be used
Не совсем,datetime.now(timezone.utc)
рекомендуется, см. Предупреждение в: docs.python.org/3.8/library/… .Для тех, кто не нуждается или не хочет использовать библиотеку pymongo для этого ... вы можете легко выполнить преобразование JSON даты и времени с помощью этого небольшого фрагмента:
Тогда используйте это так:
вывод:
источник
millis=
быть отступом внутри оператора if? Также, вероятно, лучше использовать str (obj) для получения формата ISO, который, я думаю, более распространен.datetime.now()
возвращает местное время (как наивный объект datetime), но ваш код предполагает, что онobj
находится в UTC, если он не учитывает часовой пояс. Используйтеdatetime.utcnow()
вместо этого.Вот мое решение:
Тогда вы можете использовать это так:
источник
isinstance(obj, datetime.datetime)
в TypeError, добавить больше типов для обработки и в конце добавитьstr(obj)
илиrepr(obj)
. И все ваши свалки могут просто указывать на этот специализированный класс.У меня есть приложение с похожей проблемой; мой подход состоял в том, чтобы JSONize значение datetime в виде списка из 6 элементов (год, месяц, день, час, минуты, секунды); Вы можете перейти к микросекундам в виде списка из 7 пунктов, но мне не нужно было:
производит:
источник
Мое решение (я думаю, с меньшим количеством слов):
Тогда используйте
jsondumps
вместоjson.dumps
. Он напечатает:Если хотите, позже вы можете добавить к этому другие особые случаи, просто изменив
default
метод. Пример:источник
Этот Q повторяется снова и снова - простой способ залатать модуль json так, чтобы сериализация поддерживала дату и время.
Чем использовать сериализацию JSON, как вы всегда делаете - на этот раз с датой и временем сериализуется как isoformat.
В результате: '{"созданный": "2015-08-26T14: 21: 31.853855"}'
Более подробную информацию и несколько слов предостережения смотрите по адресу: StackOverflow: JSON datetime между Python и JavaScript
источник
Метод json.dumps может принимать необязательный параметр с именем default, который, как ожидается, будет функцией. Каждый раз, когда JSON пытается преобразовать значение, он не знает, как его преобразовать, будет вызывать функцию, которую мы передали ему. Функция получит рассматриваемый объект, и ожидается, что она вернет JSON-представление объекта.
источник
если вы используете python3.7, то лучшим решением будет использование
datetime.isoformat()
иdatetime.fromisoformat()
; они работают как с наивными, так и с осознаннымиdatetime
объектами:вывод:
если вы используете python3.6 или ниже, и вас интересует только значение времени (не часовой пояс), то вы можете использовать
datetime.timestamp()
иdatetime.fromtimestamp()
вместо;если вы используете python3.6 или ниже и вам небезразличен часовой пояс, то вы можете получить его через
datetime.tzinfo
, но вы должны сами сериализовать это поле; самый простой способ сделать это - добавить еще одно поле_tzinfo
в сериализованный объект;наконец, остерегайтесь точности во всех этих примерах;
источник
Вы должны использовать
.strftime()
метод на.datetime.now()
методе, чтобы сделать его как сериализуемый метод.Вот пример:
Вывод:
источник
Вот простое решение проблемы «datetime not JSON serializable».
Выходные данные: -> {"date": "2015-12-16T04: 48: 20.024609"}
источник
Вы должны предоставить пользовательский класс кодировщика с
cls
параметромjson.dumps
. Цитировать из документов :В качестве примера используются комплексные числа, но вы также можете легко создать класс для кодирования дат (за исключением того, что JSON немного размыт в отношении дат)
источник
Самый простой способ сделать это - изменить часть слова в формате datetime на isoformat. Это значение будет эффективно представлять собой строку в isoformat, с которой json согласен.
источник
На самом деле это довольно просто. Если вам нужно часто сериализовать даты, то работайте с ними как со строками. При необходимости вы можете легко преобразовать их обратно в объекты даты и времени.
Если вам нужно работать в основном как объекты даты и времени, то перед сериализацией преобразуйте их в строки.
Как видите, вывод одинаков в обоих случаях. Только тип отличается.
источник
Если вы используете результат в представлении, обязательно верните правильный ответ. Согласно API, jsonify делает следующее:
Чтобы имитировать это поведение с помощью json.dumps, вам нужно добавить несколько дополнительных строк кода.
Вы также должны вернуть диктовку, чтобы полностью повторить ответ jsonify. Итак, весь файл будет выглядеть так
источник
pymongo
.Попробуйте это с примером, чтобы разобрать это:
источник
Мое решение ...
Хорошо, теперь некоторые тесты.
источник
Вот мое полное решение для преобразования даты и времени в JSON и обратно.
Вывод
Файл JSON
Это позволило мне импортировать и экспортировать строки, целые, числа с плавающей точкой и объекты даты и времени. Это не должно быть трудно расширить для других типов.
источник
TypeError: 'str' does not support the buffer interface
. Именно из-за'wb'
открытого режима, должно быть'w'
. Это также сказывается на десериализации, когда у нас есть данные, похожие на дату,'0000891618-05-000338'
но не совпадающие по шаблону.Преобразовать
date
вstring
источник
Обычно существует несколько способов сериализации datetime, например:
Если вы согласны с последним способом, пакет json_tricks обрабатывает даты, время и даты, включая часовые пояса.
который дает:
Так что все, что вам нужно сделать, это
а затем импортировать из
json_tricks
вместоjson
.Преимущество не сохранения его как единственной строки, int или float возникает при декодировании: если вы встречаете только строку или особенно int или float, вам нужно знать что-то о данных, чтобы знать, является ли это датой-временем. В качестве подсказки вы можете хранить метаданные, чтобы их можно было декодировать автоматически, что
json_tricks
вам и нужно. Это также легко редактируется для людей.Отказ от ответственности: это сделано мной. Потому что у меня была такая же проблема.
источник
Я получил то же сообщение об ошибке при написании сериализатора внутри класса с sqlalchemy. Так что вместо:
Я просто позаимствовал идею jgbarah об использовании isoformat () и добавил исходное значение с помощью isoformat (), чтобы оно теперь выглядело так:
источник
Быстрое исправление, если вы хотите собственное форматирование
источник
Если вы находитесь по обе стороны связи, вы можете использовать функции repr () и eval () вместе с json.
Вы не должны импортировать datetime как
Так как Эвал будет жаловаться. Или вы можете передать datetime в качестве параметра для eval. В любом случае это должно работать.
источник
Я столкнулся с той же проблемой при выводе объекта модели django в дамп как JSON. Вот как вы можете решить это.
источник
Использование вышеуказанной утилиты:
источник
Эта библиотека superjson может сделать это. И вы можете легко настроить json сериализатор для вашего собственного объекта Python, следуя этой инструкции https://superjson.readthedocs.io/index.html#extend .
Общая концепция:
ваш код должен найти правильный метод сериализации / десериализации на основе объекта python. Обычно полное имя класса является хорошим идентификатором.
И тогда ваш метод ser / deser должен быть в состоянии преобразовать ваш объект в обычный сериализуемый объект Json, комбинацию универсального типа python, dict, list, string, int, float. И реализуй свой метод дезер обратно.
источник
Я не могу на 100% правильно, но это простой способ сериализации
источник