Главная | Обратная связь | Поможем написать вашу работу!
МегаЛекции

Загрузка данных из файла 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.

Поделиться:





Воспользуйтесь поиском по сайту:



©2015 - 2024 megalektsii.ru Все авторские права принадлежат авторам лекционных материалов. Обратная связь с нами...