SON, что означает JavaScript Object Notation (нотация объектов JavaScript), является часто используемым форматом файлов (или данных). Созданный на основе JavaScript, JSON не зависит от языка: большинство языков программирования имеют парсеры для работы с файлами JSON.
JSON можно рассматривать как коллекцию пар ключ-значение, как и словарь в Python.
Вот простой файл JSON:
{"name": "Jane", "age": 28, "city": "Houston"}
Приведенный выше код — наглядный пример того, что JSON является человекочитаемым: вы можете прочитать JSON-файл и понять, какие данные он содержит. Он также легко парсится и генерируется машинами.
Почему JSON так популярен?
Широкому использованию JSON в разработке программного обеспечения и программировании способствуют многочисленные факторы. Перечислим некоторые из них.
- Удобство чтения. Как видно из приведенного выше примера, JSON легко читать и писать, что делает его отличным выбором для хранения данных, которые нужно сделать человекочитаемыми.
- Легкость. JSON не очень многословен, что облегчает его передачу по сети, а также ускоряет парсинг и загрузку.
- Структура. Это структурированный формат для хранения данных, легко читаемый людьми и машинами.
- Интероперабельность. JSON не зависит от языка и может быть использован в любом языке, а не только в JavaScript. Поэтому он отлично подходит для обмена данными между различными языками программирования.
Работа с JSON в Python
Встроенный в Python модуль json обеспечивает простой и эффективный способ работы с форматом JSON. Рассмотрим 10 примеров, демонстрирующих общие задачи, которые можно выполнять с помощью этого модуля.
Пример 1. Преобразование объекта Python в строку JSON
import json
data = {
"name": "John Doe",
"age": 28,
"city": "Houston"
}
json_data = json.dumps(data)
print(json_data)
# вывод
{"name": "John Doe", "age": 28, "city": "Houston"}
Метод dumps преобразует словарь в строку в формате json. Поэтому приведенный выше тип переменной json_data становится строкой.
type(json_data)
# вывод
str
Пример 2. Красивый вывод JSON
import json
data = {
"name": "John Doe",
"age": 28,
"city": "Houston"
}
json_data = json.dumps(data, indent=4)
print(json_data)
# вывод
{
"name": "John Doe",
"age": 28,
"city": "Houston"
}
Использование параметра indent позволяет сделать файл более читабельным.
Пример 3. Сортировка ключей
import json
data = {
"name": "John Doe",
"age": 28,
"city": "Houston"
}
json_data = json.dumps(data, sort_keys=True, indent=4)
print(json_data)
# вывод
{
"age": 28,
"city": "Houston",
"name": "John Doe"
}
Напомним, что файл JSON представляет собой набор пар ключ-значение. Вы можете сортировать эти пары по ключам с помощью параметра sort_keys.
Пример 4. Загрузка JSON в объект Python
import json
json_data = '{"name": "John Doe", "age": 28, "city": "Houston"}'
data = json.loads(json_data)
print(data)
print(data['name']) # Доступ к значению ключа 'name'
# вывод
{'name': 'John Doe', 'age': 28, 'city': 'Houston'}
John Doe
Возьмем файл JSON, сохраненный в виде строки. Преобразуем его в объект Python типа dictionary с помощью функции loads. Проверим тип этого файла.
type(data)
# вывод
dict
Пример 5. Запись контента Python в JSON-файл
import json
data = {
"name": "John Doe",
"age": 28,
"city": "Houston"
}
with open('data.json', 'w') as file:
json.dump(data, file)
В этом примере у нас есть словарь Python под названием data. Используем метод dump для записи его контента в файл JSON с именем data.json, который выглядит следующим образом:
Пример 6. Передача данных из файла JSON
import json
with open('data.json', 'r') as file:
data = json.load(file)
print(data)
# вывод
{'name': 'John Doe', 'age': 28, 'city': 'Houston'}
Метод load позволяет передать контент файла JSON в словарь Python.
Пример 7. Параметр default
Параметр default функции dumps можно использовать для сериализации сложных объектов Python, которые иначе не могут быть сериализованы. Например, следующий код вызывает ошибку TypeError из-за объекта datetime:
import json
data = {
"name": "John Doe",
"age": 28,
"city": "Houston",
"birthday": datetime.datetime.now()
}
json_data = json.dumps(data, indent=4)
# вывод
TypeError: Object of type datetime is not JSON serializable
Чтобы избежать этой ошибки, следует написать пользовательскую функцию, которая указывает функции dumps, как сериализовать этот объект:
import json
import datetime
def datetime_serializer(x):
if isinstance(x, datetime.datetime):
return x.isoformat()
data = {
"name": "John Doe",
"age": 28,
"city": "Houston",
"birthday": datetime.datetime.now()
}
json_data = json.dumps(data, indent=4, default=datetime_serializer)
print(json_data)
# вывод
{
"name": "John Doe",
"age": 28,
"city": "Houston",
"birthday": "2023-05-14T07:22:53.917531"
}
Пример 8. Параметр default и пользовательский класс
Допустим, есть пользовательский класс Person, и его нужно преобразовать экземпляр в JSON.
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
person = Person("John", 30)
json.dumps(person) # Вызывает TypeError
# вывод
ypeError: Object of type Person is not JSON serializable
Можно определить функцию, указывающую, как сериализовать объект Person:
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def person_to_dict(person):
return {"name": person.name, "age": person.age}
person = Person("John", 30)
json.dumps(person, default=person_to_dict)
# вывод
'{"name": "John", "age": 30}'
Пример 9. JSONEncoder
Класс JSONEncoder предоставляет больше контроля над процессом сериализации при преобразовании сложного объекта Python в JSON. Вместо того чтобы использовать функцию default, для json.dumps() можно создать подкласс JSONEncoder и переопределить его метод default().
Возьмем тот же пример с классом Person, но используем JSONEncoder вместо параметра default.
import json
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
class PersonEncoder(json.JSONEncoder):
def default(self, o):
if isinstance(o, Person):
return {'name': o.name, 'age': o.age}
return super().default(o)
person = Person("John", 30)
json.dumps(person, cls=PersonEncoder)
# вывод
'{"name": "John", "age": 30}'
PersonEncoder является подклассом, который наследуется от JSONEncoder.
Пример 10. Параметр skipkeys
Параметр skipkeys в dumps используется для указания того, что следует пропускать ключи, не относящиеся к основным типам (str, int, float, bool, None), вместо того, чтобы выдавать ошибку TypeError. Это удобно при работе с большими файлами.
Рассмотрим пример с использованием кортежа в качестве ключа:
import json
data = {
(1, 2): "tuple_key",
"normal_key": "value"
}
print(json.dumps(data))
# вывод
TypeError: keys must be str, int, float, bool or None, not tuple
Как видно из вывода, возникает ошибка TypeError. Если установить значение параметра skipkeys равным True, ключ кортежа будет пропущен без возникновения ошибки.
import json
data = {
(1,2): "tuple_key", # кортежи как ключи являются не JSON-сериализуемыми
"normal_key": "value"
}
print(json.dumps(data, skipkeys=True))
# вывод
{"normal_key": "value"}
Заключение
Мы познакомились с модулем json, который является мощным инструментом языка Python для работы с данными JSON. Он предоставляет функции и методы с высокой степенью гибкости и контроля над процессом сериализации и десериализации.
Примеры в этой статье охватывают такие темы, как преобразование объектов Python в JSON и обратно, работа с более сложными структурами данных и настройка процесса для обработки особых случаев.
Помните: для освоения любой новой концепции и программного инструмента необходима практика. Поэтому воспользуйтесь возможностью поэкспериментировать с этими примерами, попробовав разные варианты.