Простой Python. современный стиль программирования - читать онлайн бесплатно полную версию книги . Страница 172

Traceback (most recent call last):

# ... (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')