#Что произошло и когда проявляется ошибка
Ошибка TypeError: Object of type ... is not JSON serializable означает, что Python пытается передать в стандартный JSON неподдерживаемый объект, например datetime, set, Decimal или экземпляр собственного класса.
#Причины и диагностические признаки
| Возможная причина | Как узнать | Что делать |
|---|---|---|
| В словаре встречается datetime или DecimalСтандартная библиотека не знает, в каком виде сохранять эти типы. | TypeError называет datetime или Decimal | Явно выбрать строку ISO 8601 или представление числа по контракту. |
| Собственные объекты помещены в JSONЭкземпляр не является базовым JSON-типом. | TypeError называет класс приложения | Явно извлечь разрешённые поля в dict. |
| Используется неподходящий контейнерМножества и байты требуют соглашения о преобразовании. | TypeError для set, bytes или tuple особого вида | Определить формат и проверить обратимость. |
#Подробная пошаговая диагностика и исправление
- 1. Получите тип и место возникновения ошибкиЗапустите сериализацию тестового объекта с
json.dumps, сохраните последнюю строку TypeError и соответствующее место в коде. Не заменяйте исключениеdefault=strбез согласованного формата: такая строка может оказаться бесполезной при чтении, а данные потеряют тип.
- 2. Найдите неподдерживаемый объектВыведите имена типов только на тестовой копии структуры, без приватных значений. Сначала проверьте верхние поля словаря и массивы внутри них. При глубокой структуре используйте ограниченный рекурсивный диагностический обход либо явный список проблемных полей.
- Пример кода по темеPythonОбразец кода для файла .py в тестовой копии проекта; перед внедрением замените имена файлов на реальные.
import json from datetime import datetime obj = {"created": datetime.now()} try: json.dumps(obj) except TypeError as exc: print(type(obj["created"]).__name__, exc)
- 3. Для даты выберите строковое представлениеЕсли получатель ожидает ISO 8601, сохраняйте
datetimeчерезisoformat(); для хранения момента времени используйте aware-дату с явным смещением или UTC. При чтении обратноjson.loadsдаст строку — потребитель должен сознательно восстановить тип по схеме. - Пример кода по темеPythonОбразец кода для файла .py в тестовой копии проекта; перед внедрением замените имена файлов на реальные.
from datetime import datetime, timezone import json obj = {"created": datetime.now(timezone.utc).isoformat()} print(json.dumps(obj, ensure_ascii=False))
- 4. Для собственных классов сериализуйте разрешённые поляСоставьте обычный словарь с безопасным перечнем полей; не используйте
vars(obj)как универсальную выгрузку — в объекте могут быть внутренние поля и секреты. Дляsetзаранее определите порядок: если нужен стабильный список однородных сравнимых значений, можно использоватьsorted, но для смешанных типов потребуется другое правило. - Пример кода по темеPythonОбразец кода для файла .py в тестовой копии проекта; перед внедрением замените имена файлов на реальные.
from dataclasses import dataclass, asdict import json @dataclass class UserView: username: str active: bool print(json.dumps(asdict(UserView("Анна", True)), ensure_ascii=False))
- 5. Проверьте обратное чтение и схемуЗапишите JSON в новый файл, прочитайте его через
json.loadsи сравните ожидаемые поля, типы и значения. Для денег лучше заранее выбрать точную строку десятичного числа либо согласованное целое в минимальных единицах, а не бездумное преобразованиеDecimalв float.
- 6. Отдельно обработайте циклы и NaNЕсли ошибка не исчезла, проверьте циклические ссылки (
ValueError: Circular reference detected) и значенияNaN/бесконечность. Для строгого JSON задайтеallow_nan=False, а не оставляйте невалидные для многих систем литералыNaNиInfinity.
#Как проверить, что проблема устранена
Результат содержит только разрешённые JSON-типы; повторное чтение проходит, а значения после преобразований соответствуют документированному контракту.
#Если исправление не помогло
Нельзя безусловно сериализовать пароли, токены, объекты соединений и внутренние состояния. При отказе от преобразования поля явно сообщайте об этом, не пропускайте его молча.