Python и JSON: Полное руководство по работе с данными
Исчерпывающее руководство по работе с JSON в Python: парсинг, сериализация, обработка ошибок, продвинутые техники и best practices.
Big JSON Team
• Technical WriterExpert in JSON data manipulation, API development, and web technologies. Passionate about creating tools that make developers' lives easier.
# Python и JSON: Полное руководство по работе с данными
Python предоставляет мощные встроенные инструменты для работы с JSON. В этом подробном руководстве мы рассмотрим все аспекты работы с JSON в Python: от базового парсинга до продвинутых техник обработки данных.
Модуль json в Python
Python включает встроенный модуль json для работы с JSON данными.
Импорт модуля
import json
Основные функции
json.dumps()— Python объект → JSON строка (сериализация)json.dump()— Python объект → JSON файлjson.loads()— JSON строка → Python объект (десериализация)json.load()— JSON файл → Python объект
Парсинг JSON
Из строки (json.loads)
import json
# JSON строка
json_string = '{"имя": "Иван", "возраст": 30, "город": "Москва"}'
# Парсинг в Python словарь
данные = json.loads(json_string)
print(данные) # {'имя': 'Иван', 'возраст': 30, 'город': 'Москва'}
print(type(данные)) # <class 'dict'>
print(данные['имя']) # Иван
Из файла (json.load)
import json
# Чтение JSON из файла
with open('data.json', 'r', encoding='utf-8') as file:
данные = json.load(file)
print(данные)
Пример файла data.json:
{
"пользователь": {
"имя": "Анна Иванова",
"email": "anna@example.com",
"возраст": 28
},
"настройки": {
"тема": "темная",
"язык": "ru"
}
}
Работа с данными:
print(данные['пользователь']['имя']) # Анна Иванова
print(данные['настройки']['тема']) # темная
Сериализация в JSON
В строку (json.dumps)
import json
# Python словарь
пользователь = {
"имя": "Петр Сидоров",
"возраст": 35,
"город": "Санкт-Петербург",
"активен": True,
"баланс": None
}
# Сериализация в JSON строку
json_string = json.dumps(пользователь, ensure_ascii=False, indent=2)
print(json_string)
Результат:
{
"имя": "Петр Сидоров",
"возраст": 35,
"город": "Санкт-Петербург",
"активен": true,
"баланс": null
}
В файл (json.dump)
import json
данные = {
"компания": "ТехноСофт",
"сотрудники": [
{"имя": "Иван", "должность": "Разработчик"},
{"имя": "Мария", "должность": "Дизайнер"}
]
}
# Запись в файл
with open('output.json', 'w', encoding='utf-8') as file:
json.dump(данные, file, ensure_ascii=False, indent=2)
print("Данные сохранены в output.json")
Соответствие типов данных
Python → JSON
| Python | JSON |
|--------|------|
| dict | object |
| list, tuple | array |
| str | string |
| int, float | number |
| True | true |
| False | false |
| None | null |
Пример:python_data = {
"строка": "текст",
"число": 42,
"дробное": 3.14,
"булево": True,
"null": None,
"массив": [1, 2, 3],
"объект": {"ключ": "значение"}
}
json_string = json.dumps(python_data)
print(json_string)
# {"строка": "текст", "число": 42, "дробное": 3.14, "булево": true, "null": null, "массив": [1, 2, 3], "объект": {"ключ": "значение"}}
JSON → Python
json_string = '''
{
"string": "текст",
"number": 42,
"float": 3.14,
"boolean": true,
"null": null,
"array": [1, 2, 3],
"object": {"key": "value"}
}
'''
python_data = json.loads(json_string)
print(type(python_data)) # <class 'dict'>
print(type(python_data['array'])) # <class 'list'>
print(type(python_data['boolean'])) # <class 'bool'>
print(type(python_data['null'])) # <class 'NoneType'>
Параметры форматирования
ensure_ascii
По умолчанию True — экранирует non-ASCII символы:
данные = {"имя": "Иван", "город": "Москва"}
# С ensure_ascii=True (по умолчанию)
print(json.dumps(данные))
# {"\u0438\u043c\u044f": "\u0418\u0432\u0430\u043d", "\u0433\u043e\u0440\u043e\u0434": "\u041c\u043e\u0441\u043a\u0432\u0430"}
# С ensure_ascii=False (для кириллицы)
print(json.dumps(данные, ensure_ascii=False))
# {"имя": "Иван", "город": "Москва"}
indent
Форматирование с отступами:
данные = {"имя": "Иван", "навыки": ["Python", "JavaScript"]}
# Без отступов (компактно)
print(json.dumps(данные, ensure_ascii=False))
# {"имя": "Иван", "навыки": ["Python", "JavaScript"]}
# С отступами
print(json.dumps(данные, ensure_ascii=False, indent=2))
Результат:
{
"имя": "Иван",
"навыки": [
"Python",
"JavaScript"
]
}
sort_keys
Сортировка ключей:
данные = {"имя": "Иван", "возраст": 30, "город": "Москва"}
# Без сортировки
print(json.dumps(данные, ensure_ascii=False, indent=2))
# С сортировкой
print(json.dumps(данные, ensure_ascii=False, indent=2, sort_keys=True))
С сортировкой:
{
"возраст": 30,
"город": "Москва",
"имя": "Иван"
}
separators
Настройка разделителей:
данные = {"a": 1, "b": 2}
# По умолчанию
print(json.dumps(данные)) # {"a": 1, "b": 2}
# Компактный формат
print(json.dumps(данные, separators=(',', ':'))) # {"a":1,"b":2}
# С пробелами
print(json.dumps(данные, separators=(', ', ': '))) # {"a": 1, "b": 2}
Обработка ошибок
JSONDecodeError
import json
неправильный_json = '{"имя": "Иван", "возраст": 30,}' # Висячая запятая
try:
данные = json.loads(неправильный_json)
except json.JSONDecodeError as e:
print(f"Ошибка парсинга JSON: {e}")
print(f"Строка: {e.lineno}, Колонка: {e.colno}")
print(f"Позиция: {e.pos}")
Вывод:
Ошибка парсинга JSON: Expecting property name enclosed in double quotes: line 1 column 32 (char 31)
Строка: 1, Колонка: 32
Позиция: 31
Безопасный парсинг
def безопасный_парсинг(json_string):
"""Безопасный парсинг JSON с обработкой ошибок"""
try:
return json.loads(json_string), None
except json.JSONDecodeError as e:
return None, f"Ошибка: {e}"
except Exception as e:
return None, f"Неожиданная ошибка: {e}"
# Использование
данные, ошибка = безопасный_парсинг('{"имя": "Иван"}')
if ошибка:
print(ошибка)
else:
print(данные)
Работа с пользовательскими классами
Сериализация классов
import json
from datetime import datetime
class Пользователь:
def __init__(self, имя, возраст, email):
self.имя = имя
self.возраст = возраст
self.email = email
self.создан = datetime.now()
def to_dict(self):
"""Конвертация в словарь"""
return {
"имя": self.имя,
"возраст": self.возраст,
"email": self.email,
"создан": self.создан.isoformat()
}
# Создание объекта
пользователь = Пользователь("Иван", 30, "ivan@example.com")
# Сериализация
json_string = json.dumps(пользователь.to_dict(), ensure_ascii=False, indent=2)
print(json_string)
Кастомный JSONEncoder
import json
from datetime import datetime
from decimal import Decimal
class РасширенныйEncoder(json.JSONEncoder):
"""Кастомный encoder для специальных типов"""
def default(self, obj):
if isinstance(obj, datetime):
return obj.isoformat()
elif isinstance(obj, Decimal):
return float(obj)
elif isinstance(obj, set):
return list(obj)
elif hasattr(obj, 'to_dict'):
return obj.to_dict()
return super().default(obj)
# Использование
данные = {
"дата": datetime.now(),
"цена": Decimal("99.99"),
"теги": {"python", "json", "tutorial"},
"пользователь": пользователь
}
json_string = json.dumps(
данные,
cls=РасширенныйEncoder,
ensure_ascii=False,
indent=2
)
print(json_string)
Десериализация в классы
def dict_to_user(data):
"""Конвертация словаря в объект Пользователь"""
return Пользователь(
имя=data['имя'],
возраст=data['возраст'],
email=data['email']
)
# Парсинг
json_string = '{"имя": "Мария", "возраст": 25, "email": "maria@example.com"}'
данные = json.loads(json_string)
пользователь = dict_to_user(данные)
print(f"Имя: {пользователь.имя}, Возраст: {пользователь.возраст}")
Работа с большими JSON файлами
Streaming парсинг
import json
def обработать_большой_файл(filename):
"""Обработка большого JSON файла построчно"""
with open(filename, 'r', encoding='utf-8') as file:
# Если JSON это массив объектов
data = json.load(file)
for item in data:
# Обработка каждого элемента
обработать_элемент(item)
def обработать_элемент(item):
# Ваша логика обработки
print(f"Обработка: {item}")
ijson для streaming
import ijson
def streaming_парсинг(filename):
"""Streaming парсинг с ijson"""
with open(filename, 'rb') as file:
parser = ijson.items(file, 'item')
for item in parser:
# Обработка без загрузки всего файла в память
print(item)
Chunked чтение
def читать_частями(filename, chunk_size=1000):
"""Чтение JSON массива частями"""
with open(filename, 'r', encoding='utf-8') as file:
data = json.load(file)
for i in range(0, len(data), chunk_size):
chunk = data[i:i + chunk_size]
yield chunk
# Использование
for chunk in читать_частями('large_data.json'):
print(f"Обработка {len(chunk)} элементов")
# Обработка chunk
Валидация JSON
Базовая валидация
def валидировать_json(json_string):
"""Проверка валидности JSON"""
try:
json.loads(json_string)
return True, "JSON валиден"
except json.JSONDecodeError as e:
return False, f"Ошибка: {e}"
# Тестирование
валидный = '{"имя": "Иван"}'
невалидный = '{"имя": Иван}'
print(валидировать_json(валидный)) # (True, 'JSON валиден')
print(валидировать_json(невалидный)) # (False, 'Ошибка: ...')
С JSON Schema
import json
import jsonschema
from jsonschema import validate
# Определение схемы
схема = {
"type": "object",
"properties": {
"имя": {"type": "string", "minLength": 1},
"возраст": {"type": "integer", "minimum": 0, "maximum": 150},
"email": {"type": "string", "format": "email"}
},
"required": ["имя", "возраст"]
}
# Валидация данных
def валидировать_по_схеме(данные, схема):
try:
validate(instance=данные, schema=схема)
return True, "Данные соответствуют схеме"
except jsonschema.exceptions.ValidationError as e:
return False, f"Ошибка валидации: {e.message}"
# Тестирование
данные = {
"имя": "Иван",
"возраст": 30,
"email": "ivan@example.com"
}
результат, сообщение = валидировать_по_схеме(данные, схема)
print(сообщение)
Работа с API
GET запрос
import requests
import json
def получить_пользователей():
"""Получение данных из API"""
response = requests.get('https://api.example.com/users')
# Проверка статуса
response.raise_for_status()
# Автоматический парсинг JSON
данные = response.json()
return данные
# Использование
try:
пользователи = получить_пользователей()
for пользователь in пользователи:
print(f"{пользователь['имя']}: {пользователь['email']}")
except requests.exceptions.RequestException as e:
print(f"Ошибка запроса: {e}")
POST запрос
def создать_пользователя(имя, email):
"""Отправка данных в API"""
url = 'https://api.example.com/users'
данные = {
"имя": имя,
"email": email,
"активен": True
}
response = requests.post(
url,
json=данные, # Автоматическая сериализация в JSON
headers={'Content-Type': 'application/json'}
)
response.raise_for_status()
return response.json()
# Использование
новый_пользователь = создать_пользователя("Анна", "anna@example.com")
print(f"Создан пользователь с ID: {новый_пользователь['id']}")
Продвинутые техники
Pretty printing
import json
def красивый_вывод(данные):
"""Красивый вывод JSON в консоль"""
print(json.dumps(данные, ensure_ascii=False, indent=2, sort_keys=True))
данные = {
"пользователи": [
{"имя": "Иван", "возраст": 30},
{"имя": "Мария", "возраст": 25}
]
}
красивый_вывод(данные)
Рекурсивная обработка
def рекурсивная_обработка(obj, функция):
"""Рекурсивное применение функции ко всем строкам"""
if isinstance(obj, dict):
return {k: рекурсивная_обработка(v, функция) for k, v in obj.items()}
elif isinstance(obj, list):
return [рекурсивная_обработка(item, функция) for item in obj]
elif isinstance(obj, str):
return функция(obj)
return obj
# Пример: перевод всех строк в верхний регистр
данные = {
"имя": "иван",
"навыки": ["python", "javascript"],
"адрес": {"город": "москва"}
}
результат = рекурсивная_обработка(данные, str.upper)
print(json.dumps(результат, ensure_ascii=False, indent=2))
Фильтрация данных
def фильтровать_ключи(данные, разрешенные_ключи):
"""Фильтрация данных по разрешенным ключам"""
if isinstance(данные, dict):
return {
k: фильтровать_ключи(v, разрешенные_ключи)
for k, v in данные.items()
if k in разрешенные_ключи
}
elif isinstance(данные, list):
return [фильтровать_ключи(item, разрешенные_ключи) for item in данные]
return данные
# Пример
пользователь = {
"имя": "Иван",
"email": "ivan@example.com",
"пароль": "secret", # Должен быть удален
"возраст": 30
}
безопасные_данные = фильтровать_ключи(
пользователь,
{"имя", "email", "возраст"}
)
print(json.dumps(безопасные_данные, ensure_ascii=False, indent=2))
Best Practices
1. Всегда используйте encoding='utf-8'
# Правильно
with open('data.json', 'r', encoding='utf-8') as f:
данные = json.load(f)
# Может вызвать проблемы с кириллицей
with open('data.json', 'r') as f: # Плохо
данные = json.load(f)
2. Используйте ensure_ascii=False для кириллицы
# Правильно для русского текста
json.dumps(данные, ensure_ascii=False)
# Создаст \\uXXXX для кириллицы
json.dumps(данные) # ensure_ascii=True по умолчанию
3. Обрабатывайте ошибки
try:
with open('data.json', 'r', encoding='utf-8') as f:
данные = json.load(f)
except FileNotFoundError:
print("Файл не найден")
except json.JSONDecodeError as e:
print(f"Ошибка парсинга: {e}")
except Exception as e:
print(f"Неожиданная ошибка: {e}")
4. Используйте context managers
# Правильно — файл автоматически закроется
with open('data.json', 'r', encoding='utf-8') as f:
данные = json.load(f)
# Плохо — нужно явно закрывать
f = open('data.json', 'r', encoding='utf-8')
данные = json.load(f)
f.close()
5. Валидируйте внешние данные
def обработать_api_ответ(json_string):
try:
данные = json.loads(json_string)
# Валидация структуры
if not isinstance(данные, dict):
raise ValueError("Ожидается объект")
if 'status' not in данные:
raise ValueError("Отсутствует поле status")
return данные
except (json.JSONDecodeError, ValueError) as e:
print(f"Ошибка: {e}")
return None
Заключение
Python предоставляет мощные и удобные инструменты для работы с JSON. Модуль json покрывает большинство потребностей, а для специальных случаев доступны дополнительные библиотеки.
- Используйте
json.loads()иjson.dumps()для строк - Используйте
json.load()иjson.dump()для файлов - Всегда указывайте
encoding='utf-8'иensure_ascii=False - Обрабатывайте исключения
JSONDecodeError - Используйте кастомные encoders для специальных типов
- Для больших файлов применяйте streaming
С этим руководством вы готовы эффективно работать с JSON в Python!
Похожие статьи
Файл JSON: Полное руководство по работе с .json файлами
Узнайте всё о файлах JSON: как их создавать, открывать, редактировать и использовать в различных приложениях и языках программирования.
JavaScript и JSON: Полное руководство для разработчиков
Комплексное руководство по работе с JSON в JavaScript: встроенные методы, парсинг, сериализация, обработка ошибок и продвинутые техники.
Работа с большими файлами JSON: Оптимизация и производительность
Эффективные методы обработки больших JSON файлов: streaming, chunking, оптимизация памяти и производительности.