# ... (deleted stack trace to save trees)
TypeError: datetime.datetime(2013, 2, 22, 3, 49, 27, 483336) is not JSON serializable
>>>
Это может случиться, поскольку стандарт JSON не определяет типы даты
или времени — он ожидает, что вы укажете ему, как с ними работать. Вы можете
преобразовать формат datetime во что-то, что JSON понимает, вроде строки или
значения времени epoch (его мы рассмотрим в главе 10):
>>> now_str = str(now)
>>> json.dumps(now_str)
'"2013-02-22 03:49:27.483336"'
>>> from time import mktime
>>> now_epoch = int(mktime(now.timetuple()))
>>> json.dumps(now_epoch)
'1361526567'
Если значение datetime встретится между нормальными сконвертированны-
ми типами данных, может быть неприятно выполнять такие особые преобразо-
вания. Вы можете изменить то, как JSON будет закодирован, с помощью на-
следования, что описано в разделе «Наследование» главы 6. Документация JSON
для Python содержит пример такого переопределения для комплексных чисел,
что также заставляет JSON притвориться мертвым. Напишем переопределение
для datetime:
>>> class DTEncoder(json.JSONEncoder):
... def default(self, obj):
... # isinstance() checks the type of obj
... if isinstance(obj, datetime.datetime):
... return int(mktime(obj.timetuple()))
... # else it's something the normal decoder knows:
... return json.JSONEncoder.default(self, obj)
...
>>> json.dumps(now, cls=DTEncoder)
'1361526567'
226
Глава 8. Данные должны куда-то попадать
Новый класс DTEncoder является подклассом, или классом-потомком, класса
JSONEncoder. Нам нужно лишь переопределить его метод default(), добавив обра-
ботку datetime. Наследование гарантирует, что все остальное будет обработано
родительским классом.
Функция isinstance() проверяет, является ли объект obj объектом класса
datetime.datetime. Поскольку в Python все является объектом, функция isinstance()
работает везде:
>>> type(now)
<class 'datetime.datetime'>
>>> isinstance(now, datetime.datetime)
True
>>> type(234)
<class 'int'>
>>> isinstance(234, int)
True
>>> type('hey')