Лекции.Орг


Поиск:




Категории:

Астрономия
Биология
География
Другие языки
Интернет
Информатика
История
Культура
Литература
Логика
Математика
Медицина
Механика
Охрана труда
Педагогика
Политика
Право
Психология
Религия
Риторика
Социология
Спорт
Строительство
Технология
Транспорт
Физика
Философия
Финансы
Химия
Экология
Экономика
Электроника

 

 

 

 


Загрузка данных из файла json




Как и в модуле pickle в модуле json есть функция load(), которая принимает на вход поток, читает из него данные в формате json и создает новый объект Python, который будет копией структуры данных записанной в json файле.

>>> shell
2
>>> del entry ①
>>> entry
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'entry' is not defined
>>> import json
>>> with open('entry.json', 'r', encoding='utf-8') as f:
... entry = json.load(f) ②
...
>>> entry ③
{'comments_link': None,
'internal_id': {'__class__': 'bytes', '__value__': [222, 213, 180, 248]},
'title': 'Dive into history, 2009 edition',
'tags': ['diveintopython', 'docbook', 'html'],
'article_link': 'http://diveintomark.org/archives/2009/03/27/dive-into-history-2009-edition',
'published_date': {'__class__': 'time.asctime', '__value__': 'Fri Mar 27 22:20:42 2009'},
'published': True}

① Для демонстрации переключитесь во вторую консоль Python и удалите структуру данных entry которую вы создали ранее в этой главе при помощи модуля Pickle.

② В простейшем случае функция json.load() работает так же как и функция pickle.load(). Вы передаете ей объект потока, а получаете в результате новый объект Python.

③ У меня есть хорошие и плохие новости. Хорошие новости в том, что функция json.load() успешно прочитала файл entry.json, который вы создали в первой консоли Python и создала новый объект Python, который содержит данные. А теперь плохие новости: она не воссоздала оригинальную структуру данных entry. Два значения 'internal_id' и 'published_date' были созданы как словари - а именно, как словари со значениями которые совместимы с json (именно их вы создали в функции преобразования to_json())

Функция json.load() ничего не знает о функции преобразования, которую вы могли передать в json.dump(). Теперь вам нужно создать функцию, обратную to_json() — функцию, которая примет выборочно преобразованный json объект и преобразует его обратно в оригинальный объект Python.

# add this to customserializer.py
def from_json(json_object): ①
if '__class__' in json_object: ②
if json_object['__class__'] == 'time.asctime':
return time.strptime(json_object['__value__']) ③
if json_object['__class__'] == 'bytes':
return bytes(json_object['__value__']) ④
return json_object

① Эта функция преобразования так же принимает один параметр и возвращает одно значение. Но параметр который она принимает - не строка, это объект Python - результат десереализации строки JSON, в которую был преобразован объект Python.

② Все что вам нужно, так это проверить, содержит ли данный объект ключ '__class__', который создала функция to_json(). Если так, то значение найденное по этому ключу, расскажет вам, как декодировать этот объект обратно в оригинальный объект Python

③ Чтобы декодировать строку времени возвращаемую функцией time.asctime() вам нужно использовать функцию time.strptime(). Эта функция принимает параметром форматированную строку времени(в определяемом формате, но по умолчанию этот формат совпадает с форматом time.asctime()) и возвращает time.struct_time

④ Для преобразования списка чисел обратно в объекты bytes вы можете использовать функцию bytes()

Вот и все, всего два типа данных которые были обработаны функцией to_json() и теперь эти же типы данных были обработаны функцией from_json(). Вот результат:

>>> shell
2
>>> import customserializer
>>> with open('entry.json', 'r', encoding='utf-8') as f:
... entry = json.load(f, object_hook=customserializer.from_json) ①
...
>>> entry ②
{'comments_link': None,
'internal_id': b'\xDE\xD5\xB4\xF8',
'title': 'Dive into history, 2009 edition',
'tags': ['diveintopython', 'docbook', 'html'],
'article_link': 'http://diveintomark.org/archives/2009/03/27/dive-into-history-2009-edition',
'published_date': time.struct_time(tm_year=2009, tm_mon=3, tm_mday=27, tm_hour=22, tm_min=20, tm_sec=42, tm_wday=4, tm_yday=86, tm_isdst=-1),
'published': True}

① Чтобы встроить функцию from_json() в процесс десериализации, передайте ее в параметре object_hook в вызове функции json.load(). Функции которые принимают функции, как удобно!

② Структура данных entry теперь содержит ключ 'internal_id' со значением типа bytes. Также она содержит ключ 'published_date' со значением time.struct_time.

Хотя остался еще один глюк.

>>> shell
1
>>> import customserializer
>>> with open('entry.json', 'r', encoding='utf-8') as f:
... entry2 = json.load(f, object_hook=customserializer.from_json)
...
>>> entry2 == entry ①
False
>>> entry['tags'] ②
('diveintopython', 'docbook', 'html')
>>> entry2['tags'] ③
['diveintopython', 'docbook', 'html']

① Даже после встраивания функции to_json() в сериализацию и функции from_json() в десериализацию мы все еще не получили полную копию оригинальной структуры данных. Почему нет?

② В оригинальной структуре данных entry значение по ключу 'tags' было кортежем строк.

③ Но в воссозданной структуре данных entry2 значение по ключу 'tags' - это список строк. JSON не видит различий между кортежами и списками, в нем есть только один похожий на список тип данных, массив, и модуль json по-тихому преобразует и списки и кортежи в массивы json во время сериализации. Для большинства случаев, вы можете проигнорировать различие между списками и кортежами, но это нужно помнить, когда работаешь с модулем json.





Поделиться с друзьями:


Дата добавления: 2016-11-18; Мы поможем в написании ваших работ!; просмотров: 578 | Нарушение авторских прав


Поиск на сайте:

Лучшие изречения:

Логика может привести Вас от пункта А к пункту Б, а воображение — куда угодно © Альберт Эйнштейн
==> читать все изречения...

2303 - | 2226 -


© 2015-2025 lektsii.org - Контакты - Последнее добавление

Ген: 0.008 с.