В этом руководстве мы рассмотрим синтаксис и типы данных JSON, а также библиотеки и методы Python, используемые для парсинга JSON в Python.
JSON (JavaScript Object Notation) — это текстовый формат данных, используемый для обмена и хранения данных между веб-приложениями. Он упрощает процесс передачи данных между различными языками программирования и платформами.
Стандарт JSON стал все более популярным в последние годы. Это простой и гибкий способ представления данных, который легко понимается и обрабатывается как людьми, так и машинами. JSON состоит из пар «ключ-значение», заключенных в фигурные скобки и разделенных двоеточием.
Python предоставляет различные инструменты, библиотеки и методы для парсинга JSON в Python и управления данными JSON, что делает его популярным выбором для аналитиков данных, веб-разработчиков и специалистов по данным.
В этом руководстве мы рассмотрим синтаксис и типы данных JSON, а также библиотеки и методы Python, используемые для парсинга JSON в Python, включая более продвинутые варианты, такие как JMESPath и ChompJS, которые очень полезны для сбора данных из интернета.
Чтение JSON
Одной из наиболее распространенных задач при работе с данными JSON является чтение их содержимого. Python предоставляет несколько встроенных библиотек для чтения JSON из файлов, API и веб-приложений. Для чтения JSON-данных можно использовать встроенный модуль json (JSON Encoder и Decoder) в Python.
Модуль json предоставляет два метода: loads и load, которые позволяют выполнять парсинг JSON в Python: строк JSON и файлов JSON, соответственно, для преобразования JSON в объекты Python, такие как списки и словари. Далее приведен пример того, как преобразовать строку JSON в объект Python с помощью метода loads.
import json
json_input = '{ "make": "Tesla", "model": "Model 3", "year": 2022, "color": "Red" }'
json_data = json.loads(json_input)
print(json_data) # Вывод: {'make': 'Tesla', 'model': 'Model 3', 'year': 2022, 'color': 'Red'}
content_copydownloadUse code with caution.Python
Далее мы покажем пример использования метода load. Дан файл JSON:
{
"make": "Tesla",
"model": "Model 3",
"year": 2022,
"color": "Red"
}
content_copydownloadUse code with caution.Json
Мы загружаем данные, используя менеджер контекста with open() и json.load(), чтобы загрузить содержимое JSON-файла в словарь Python.
import json
with open('data.json') as f:
json_data = json.load(f)
print(json_data) # Вывод: {'make': 'Tesla', 'model': 'Model 3', 'year': 2022, 'color': 'Red'}
content_copydownloadUse code with caution.Python
Парсинг JSON в Python: анализ данных
После загрузки JSON-данных в Python вы можете получить доступ к определенным элементам данных, используя ключи, предоставленные в структуре JSON. В JSON данные обычно хранятся в массиве или объекте. Для доступа к данным внутри массива JSON можно использовать индексацию массива, а для доступа к данным внутри объекта можно использовать пары «ключ-значение».
import json
json_string ='{"numbers": [1, 2, 3], "car": {"model": "Model X", "year": 2022}}'
json_data = json.loads(json_string)
# Доступ к элементам массива JSON с использованием индексации массива
print(json_data['numbers'][0]) # Вывод: 1
# Доступ к элементам JSON с использованием ключей
print(json_data['car']['model']) # Вывод: Model X
content_copydownloadUse code with caution.Python
В приведенном выше примере внутри структуры JSON есть объект car, который содержит два сопоставления (model и year). Это пример вложенной структуры JSON, где один объект содержится внутри другого объекта. Для доступа к элементам внутри вложенных структур JSON требуется использовать несколько ключей или индексов для прохода по структуре при парсинге JSON в Python.
Взаимозаменяемость объектов JSON и Python
JSON — это строковый формат, используемый для обмена данными, который имеет схожий синтаксис с синтаксисом литералов объектов-словарей Python. Однако важно помнить, что JSON — это не то же самое, что словарь Python. При загрузке JSON-данных в Python они преобразуются в объект Python, обычно словарь или список, и ими можно управлять с помощью стандартных методов объектов Python. Когда данные готовы к сохранению, вам потребуется преобразовать их обратно в формат JSON с помощью функции json.dumps. Важно помнить об этом различии между двумя форматами при парсинге JSON в Python.
Изменение данных JSON
Работа с JSON в Python также включает изменение данных путем добавления, обновления или удаления элементов. В этой статье мы сосредоточимся на основах, поэтому будем использовать встроенный пакет json, поскольку он предоставляет все основные функции, необходимые для выполнения этих задач парсинга JSON в Python.
Добавление элемента
Чтобы добавить элемент, вы можете изменить соответствующее сопоставление в объекте JSON, используя стандартный синтаксис словаря. Например:
import json
json_string = '{"model": "Model X", "year": 2022}'
json_data = json.loads(json_string)
json_data['color'] = 'red'
print(json_data) # Вывод: {'model': 'Model X', 'year': 2022, 'color': 'red'}
content_copydownloadUse code with caution.Python
Обновление элемента
Обновление элемента следует той же логике, что и в предыдущем фрагменте кода, но вместо создания нового ключа будет заменено значение существующего ключа при парсинге JSON в Python.
import json
json_string = '{"model": "Model X", "year": 2022}'
json_data = json.loads(json_string)
json_data['year'] = 2023
print(json_data) # Вывод: {'model': 'Model X', 'year': 2023}
content_copydownloadUse code with caution.Python
Другой подход к добавлению и/или обновлению значений в словаре Python — использование метода update(). Он добавляет или обновляет элементы в словаре, используя значения из другого словаря или из итерируемого объекта, содержащего пары «ключ-значение».
import json
json_string = '{"model": "Model X", "year": 2022}'
json_data = json.loads(json_string)
more_json_string = '{"model": "Model S", "color": "Red"}'
more_json_data = json.loads(more_json_string)
json_data.update(more_json_data)
print(json_data) # Вывод: {'model': 'Model S', 'year': 2022, 'color': 'Red'}
content_copydownloadUse code with caution.Python
Удаление элемента
Чтобы удалить элемент из объекта JSON, можно использовать ключевое слово del для удаления соответствующего значения при парсинге JSON в Python.
import json
json_string = '{"model": "Model X", "year": 2022}'
json_data = json.loads(json_string)
del json_data['year']
content_copydownloadUse code with caution.Python
Другой подход к удалению элемента из словаря с данными JSON — использование метода pop, который позволяет получить значение и использовать его одновременно с удалением.
import json
json_string = '{"model": "Model X", "year": 2022}'
json_data = json.loads(json_string)
year = json_data.pop('year')
print(year) # Вывод: 2022
print(json_data) # Вывод: {'model': 'Model X'}
content_copydownloadUse code with caution.Python
Будьте осторожны, попытка удалить элемент с помощью del, когда элемента нет, вызовет исключение KeyError. Метод pop, с другой стороны, вернет None, если не найдет ключ. Способы использования del, когда вы не уверены в наличии ключа, — это либо проверить, существует ли ключ, при парсинге JSON в Python.
import json
json_string = '{"model": "Model X", "year": 2022}'
json_data = json.loads(json_string)
if 'year' in json_data:
del json_data['year']
else:
print('Ключ не найден')
# или обернуть операцию del блоком try/catch
json_string = '{"model": "Model X", "year": 2022}'
json_data = json.loads(json_string)
try:
del json_data['year']
except KeyError:
print('Ключ не найден')
content_copydownloadUse code with caution.Python
Обработка ошибок Python: проверять или просить?
Когда дело доходит до обработки ошибок в Python, есть два метода: «проверяй перед тем, как прыгать» и «проси прощения». Первый включает проверку состояния программы перед выполнением каждой операции, а второй пытается выполнить операцию и перехватывает любые исключения в случае сбоя при парсинге JSON в Python.
Подход «проси прощения» чаще используется в Python и предполагает, что ошибки являются обычной частью потока программы. Этот подход обеспечивает корректный способ обработки ошибок, делая код более легким для чтения и написания. Хотя он может быть менее эффективным, чем подход «проверяй перед тем, как прыгать», обработка исключений в Python оптимизирована для него, и разница в производительности обычно незначительна при парсинге JSON в Python.
Сохранение JSON
После изменения предыдущего JSON-файла или JSON-строки вы можете захотеть сохранить измененные данные обратно в JSON-файл или экспортировать их как JSON-строку для хранения данных. Метод json.dump() позволяет сохранить JSON-объект в файл, а json.dumps() возвращает строковое представление JSON-объекта.
Сохранение JSON в файл с помощью json.dump() и менеджера контекста with open() с настройкой режима записи («w»):
import json
data = '{"model": "Model X", "year": 2022}'
# Сохраняет словарь с именем data как объект JSON в файл data.json
with open("data.json", "w") as f:
json.dump(data, f)
content_copydownloadUse code with caution.Python
Преобразование объекта Python в JSON-строку с помощью json.dumps():
import json
data = {"model": "Model X", "year": 2022}
# Преобразует словарь data в строковое представление JSON
json_string = json.dumps(data)
print(json_string) # Вывод: {"model": "Model X", "year": 2022}
content_copydownloadUse code with caution.Python
Продвинутые методы парсинга JSON в Python
При обходе данных JSON в Python, в зависимости от сложности объекта, существуют более продвинутые библиотеки, которые помогут вам получить доступ к данным с меньшим количеством кода.
JMESPath
JMESPath — это язык запросов, разработанный для работы с данными JSON. Он позволяет извлекать определенные части структуры JSON на основе поискового запроса. JMESPath хорошо подходит для продвинутых задач парсинга JSON в Python, поскольку он может с легкостью обрабатывать сложные, вложенные структуры JSON. В то же время он прост в использовании на начальном уровне, что делает его доступным инструментом для всех, кто работает с данными JSON.
Вот пример использования библиотеки jmespath в Python для извлечения данных:
import json
import jmespath
json_string = '{"numbers": [1, 2, 3], "car": {"model": "Model X", "year": 2022}}'
json_data = json.loads(json_string)
# Доступ к вложенному JSON
name = jmespath.search('car.model', json_data) # Результат: Model X
# Получение первого числа из numbers
first_number = jmespath.search('numbers[0]', json_data) # Результат: 1
content_copydownloadUse code with caution.Python
Эти примеры демонстрируют только основы того, что может делать JMESPath. Запросы JMESPath также могут фильтровать и преобразовывать данные JSON при парсинге JSON в Python. Например, вы можете использовать JMESPath для фильтрации списка объектов на основе определенного значения или для извлечения определенных частей объекта и преобразования их в новую структуру.
Предположим, у нас есть массив JSON с объектами автомобилей, каждый из которых содержит такую информацию, как марка автомобиля, модель, год выпуска и цена:
cars = [
{"make": "Toyota", "model": "Corolla", "year": 2018, "price": 15000},
{"make": "Honda", "model": "Civic", "year": 2020, "price": 20000},
{"make": "Ford", "model": "Mustang", "year": 2015, "price": 25000},
{"make": "Tesla", "model": "Model S", "year": 2021, "price": 50000}
]
content_copydownloadUse code with caution.Python
Мы можем использовать JMESPath для фильтрации этого списка и возврата только тех автомобилей, которые находятся в определенном ценовом диапазоне, и преобразовать результат в новую структуру, которая содержит только марку, модель и год выпуска автомобиля при парсинге JSON в Python:
import jmespath
result = jmespath.search("""
[?price <= `25000`].{
Make: make,
Model: model,
Year: year
}
""", cars)
content_copydownloadUse code with caution.Python
Вывод этого кода будет следующим:
[
{'Make': 'Toyota', 'Model': 'Corolla', 'Year': 2018},
{'Make': 'Honda', 'Model': 'Civic', 'Year': 2020},
{'Make': 'Ford', 'Model': 'Mustang', 'Year': 2015}
]
content_copydownloadUse code with caution.Python
Освоение JMESPath — это верный способ навсегда избавиться от головной боли при парсинге JSON в Python. Даже сложные структуры JSON, такие как те, которые часто встречаются при сборе данных из интернета при работе с JSON-документом, найденным на веб-сайтах, можно легко обрабатывать с помощью обширных функций JMESPath.
JMESPath доступен не только для Python, но и для многих других языков программирования, таких как Java и Ruby. Чтобы узнать больше о JMESPath и его функциях, посетите официальный веб-сайт.
ChompJS
Сбор данных из интернета включает сбор данных с веб-сайтов, которые могут быть встроены в объекты JavaScript, инициализирующие страницу. В то время как функция стандартной библиотеки json.loads() извлекает данные из объектов JSON, она ограничена допустимыми объектами JSON. Проблема заключается в том, что не все допустимые объекты JavaScript также являются допустимыми JSON. Например, все эти строки являются допустимыми объектами JavaScript, но не являются допустимыми JSON:
- «{‘a’: ‘b’}» — не является допустимым JSON, поскольку для заключения в кавычки используется символ ‘.
- ‘{a: «b»}’ — не является допустимым JSON, поскольку имя свойства не заключено в кавычки.
- ‘{«a»: [1, 2, 3,]}’— не является допустимым JSON, поскольку в конце массива есть лишний символ ,.
- ‘{«a»: .99}’ — не является допустимым JSON, поскольку в значении с плавающей запятой отсутствует ведущий 0.
Библиотека chompjs была разработана для обхода этого ограничения и позволяет преобразовывать такие объекты JavaScript в правильные словари Python при парсинге JSON в Python:
import chompjs
chompjs.parse_js_object("{'a': 'b'}") # Вывод: {u'a': u'b'}
chompjs.parse_js_object('{a: "b"}') # Вывод: {u'a': u'b'}
chompjs.parse_js_object('{"a": [1, 2, 3,]}') # Вывод: {u'a': [1, 2, 3]}
content_copydownloadUse code with caution.Python
chompjs работает путем парсинга JSON в Python: объекта JavaScript и преобразования его в допустимый словарь Python. В дополнение к парсингу JSON в Python: простых объектов, он также может обрабатывать объекты, содержащие встроенные методы, сохраняя их код в строке.
Одним из преимуществ использования chompjs по сравнению с json.loads является то, что он может обрабатывать более широкий спектр объектов JavaScript. Например, chompjs может обрабатывать объекты, которые используют одинарные кавычки вместо двойных для имен свойств и значений. Он также может обрабатывать объекты, которые имеют лишние запятые в конце массивов или объектов при парсинге JSON в Python.
Работа с пользовательскими объектами Python
Почти все языки программирования поддерживают пользовательские объекты, которые создаются с использованием концепций объектно-ориентированного программирования. Однако, хотя основные принципы объектно-ориентированного программирования одинаковы для разных языков программирования, синтаксис, функции и варианты использования пользовательских объектов могут различаться в зависимости от языка.
Пользовательские объекты Python обычно создаются с использованием классов, которые могут инкапсулировать данные и поведение.
Одним из примеров пользовательского объекта Python является класс Car:
class Car:
def __init__(self, make, model, year, price):
self.make = make
self.model = model
self.year = year
self.price = price
content_copydownloadUse code with caution.Python
Чтобы создать новый объект Car, мы можем просто вызвать конструктор Car с соответствующими аргументами при парсинге JSON в Python:
car = Car("Toyota", "Camry", 2022, 25000)
content_copydownloadUse code with caution.Python
Если мы попытаемся сериализовать объект Car как есть, мы получим TypeError:
car_json = json.dumps(car)
# TypeError: Объект типа 'Car' не является сериализуемым для JSON
content_copydownloadUse code with caution.Python
Эта ошибка возникает из-за того, что json.dumps() не знает, как сериализовать наш объект Car. По умолчанию модуль json в Python может сериализовать только определенные типы объектов, такие как строки, числа и списки/словари. Чтобы сериализовать наш объект Car в строку JSON, нам нужно создать пользовательский класс кодирования для парсинга JSON в Python.
Кодирование
Мы можем создать собственный кодировщик, унаследовав его от json.JSONEncoder и переопределив метод default. Это позволяет нам преобразовывать объекты Python в строки JSON. Метод default вызывается кодировщиком JSON для объектов, которые не являются сериализуемыми по умолчанию при парсинге JSON в Python.
import json
class CarEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, Car):
return {"make": obj.make, "model": obj.model, "year": obj.year, "price": obj.price}
return super().default(obj)
content_copydownloadUse code with caution.Python
Внутри метода default мы проверяем, является ли кодируемый объект экземпляром класса Car. Если да, мы возвращаем словарь с атрибутами. Если это не экземпляр класса Car, мы вызываем метод default родительского класса для обработки кодирования при парсинге JSON в Python.
car = Car("Toyota", "Camry", 2022, 25000)
car_json = CarEncoder().encode(car)
print(car_json) # Вывод: {"make": "Toyota", "model": "Camry", "year": 2022, "price": 25000}
content_copydownloadUse code with caution.Python
Используя пользовательский класс кодирования, мы можем настроить способ сериализации наших объектов в JSON и обрабатывать любые особые случаи, которые могут не поддерживаться поведением кодирования по умолчанию при парсинге JSON в Python.
Декодирование
Точно так же, как мы можем использовать пользовательские классы кодирования для сериализации пользовательских объектов в JSON, мы также можем использовать пользовательские классы декодирования для декодирования строк JSON обратно в наши пользовательские объекты при парсинге JSON в Python.
В текущем состоянии нашего CarEncoder мы не занимаемся декодированием объекта обратно в его пользовательский объект. Если мы используем метод decode, мы получим только словарь со значениями, а не объект Car.
car_json = '{"make": "Toyota", "model": "Camry", "year": 2022, "price": 25000}'
car_dict = json.loads(car_json)
print(car_dict) # Вывод: {"make": "Toyota", "model": "Camry", "year": 2022, "price": 25000}
content_copydownloadUse code with caution.Python
Как видите, вывод — это просто словарь с атрибутами объекта Car. Если мы хотим преобразовать этот словарь обратно в объект Car, нам нужно создать собственный класс декодера для использования в методе json.loads() при парсинге JSON в Python.
Добавление метаданных
Метаданные здесь относятся к дополнительной информации о данных. Это может включать информацию о структуре, формате или другие описательные сведения, которые помогают понять или обработать данные при парсинге JSON в Python.
Один из способов сделать так, чтобы декодер мог узнать тип объекта, который он должен преобразовать, — это добавить метаданные, привязанные к типу объекта, при его кодировании.
if isinstance(obj, Car):
return {"make": obj.make, "model": obj.model, "year": obj.year, "price": obj.price}
content_copydownloadUse code with caution.Python
Добавим к нашему предыдущему CarEncoder метаданные типа при парсинге JSON в Python:
if isinstance(obj, Car):
return {"__type__": "Car", "make": obj.make, "model": obj.model, "year": obj.year, "price": obj.price}
content_copydownloadUse code with caution.Python
Мы можем использовать это с пользовательским классом декодирования, чтобы определить, какой объект создать при парсинге JSON в Python.
car = Car("Toyota", "Camry", 2022, 25000)
car_json = json.dumps(car, cls=CarEncoder)
print(car_json) # Вывод: {"__type__": "Car", "make": "Toyota", "model": "Camry", "year": 2022, "price": 25000}
content_copydownloadUse code with caution.Python
Вот класс CarDecoder, который позволит нам передавать данные в виде строки JSON и возвращать пользовательский объект Python при парсинге JSON в Python.
class CarDecoder(json.JSONDecoder):
def __init__(self, *args, **kwargs):
super().__init__(object_hook=self.object_hook, *args, **kwargs)
def object_hook(self, dct):
if '__type__' in dct and dct['__type__'] == 'Car':
return Car(dct['make'], dct['model'], dct['year'], dct['price'])
return dct
content_copydownloadUse code with caution.Python
Затем мы можем использовать CarDecoder в методе json.loads() в качестве параметра cls при парсинге JSON в Python.
car_json = '{"__type__": "Car", "make": "Toyota", "model": "Camry", "year": 2022, "price": 25000}'
car = json.loads(car_json, cls=CarDecoder)
print(car.make) # Вывод: "Toyota"
print(car.model) # Вывод: "Camry"
print(car.year) # Вывод: 2022
print(car.price) # Вывод: 25000
content_copydownloadUse code with caution.Python
Заключение
В этом руководстве мы рассмотрели основы чтения и парсинга JSON в Python, а также способы доступа к данным JSON и их изменения с помощью встроенного пакета json в Python. Мы также обсудили более продвинутые варианты парсинга JSON в Python, такие как JMESPath и ChompJS, которые полезны для сбора данных из интернета. Благодаря знаниям, полученным из этого руководства, вы сможете эффективно работать с данными JSON в Python и интегрировать их в свой рабочий процесс разработчика. Если у вас есть вопросы, <a href=»mailto:info@datalopata.ru»>свяжитесь с нами</a>.