Отправка JSON с Python Requests: параметры, примеры, интеграции
Для кого эта статья:
- Python-разработчики, начинающие или улучшившие свои навыки работы с API
- Студенты курсов по программированию или веб-разработке
Специалисты, желающие повысить квалификацию в интеграциях и работе с веб-сервисами
Работа с веб-API стала неотъемлемой частью процесса разработки программного обеспечения. Передача данных в формате JSON через HTTP-запросы — ежедневная задача для Python-разработчика. Библиотека Requests делает этот процесс элегантным, но многие спотыкаются на подводных камнях: правильное кодирование, различия между параметрами запросов, обработка ошибок. Давайте раз и навсегда разложим по полочкам все нюансы отправки JSON-данных с Python Requests, чтобы ваши интеграции с API работали безотказно с первой попытки. 🐍💻
Не тратьте время на болезненный метод проб и ошибок! На курсе Обучение Python-разработке от Skypro вы за 9 месяцев освоите не только базовые принципы работы с Requests и JSON, но и погрузитесь в разработку полноценных веб-приложений с использованием Django и Flask. Наши студенты создают рабочие проекты с реальными API-интеграциями уже к середине обучения. Инвестируйте в навыки, которые востребованы на рынке прямо сейчас!
Основы отправки JSON данных с Python Requests
Библиотека Requests — стандарт де-факто для HTTP-запросов в Python. Когда дело касается отправки JSON данных, принципиально важно понимать базовые механизмы.
Прежде всего, убедитесь, что библиотека установлена:
pip install requests
Отправка JSON-данных с Requests сводится к трём ключевым шагам:
- Подготовка данных в формате Python-словаря
- Преобразование этих данных в JSON при отправке запроса
- Корректная обработка полученного ответа
Простейший пример отправки JSON-данных выглядит так:
import requests
data = {
"username": "python_developer",
"password": "secure_password123",
"email": "developer@example.com"
}
response = requests.post('https://api.example.com/users', json=data)
print(response.status_code)
print(response.json())
Ключевой момент здесь — использование параметра json, который автоматически сериализует Python-словарь в JSON-строку и устанавливает соответствующий заголовок Content-Type: application/json.
Важно понимать основные HTTP-методы при работе с JSON и REST API:
| HTTP-метод | Действие | Пример использования |
|---|---|---|
| GET | Получение данных | Запрос списка пользователей |
| POST | Создание ресурса | Регистрация нового пользователя |
| PUT | Полное обновление ресурса | Обновление всего профиля |
| PATCH | Частичное обновление | Изменение только email пользователя |
| DELETE | Удаление ресурса | Удаление аккаунта пользователя |
JSON (JavaScript Object Notation) — легковесный формат обмена данными, который стал стандартом для веб-API благодаря своей читаемости и совместимости с JavaScript. В Python с JSON работают через встроенный модуль json, но Requests берет эту задачу на себя.
Александр Петров, Python-разработчик со стажем 8 лет
Однажды я потратил три дня, пытаясь понять, почему наше приложение не может авторизоваться через API партнера. Логи показывали ошибку 400, но причина была неясна. Оказалось, что мы отправляли JSON с использованием параметра
data, а неjson. Визуально в коде разница была минимальна:PythonСкопировать код# Не работало: requests.post(url, data=credentials) # Заработало: requests.post(url, json=credentials)Это был ценный урок: параметр
jsonавтоматически устанавливает правильные заголовки и кодирует данные. С тех пор для JSON всегда использую именно его, и проблем не возникало. Такие простые ошибки могут отнять часы отладки.

Метод post() для работы с API: структура и параметры
Метод post() библиотеки Requests — основной инструмент для отправки данных на сервер. Его сигнатура содержит множество параметров, но для работы с JSON критически важны следующие:
requests.post(url,
data=None,
json=None,
headers={},
cookies=None,
timeout=None,
auth=None)
Параметры запроса при работе с JSON:
- url — адрес API-эндпоинта
- json — данные в виде Python-словаря, которые будут автоматически сериализованы в JSON
- headers — HTTP-заголовки запроса (часто включают токены авторизации)
- timeout — максимальное время ожидания ответа в секундах
- auth — кортеж с логином и паролем для базовой HTTP-аутентификации
Пример отправки аутентифицированного JSON-запроса с заголовками:
import requests
url = 'https://api.example.com/orders'
headers = {
'Authorization': 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...',
'X-API-Version': '2.1'
}
payload = {
'product_id': 1234,
'quantity': 5,
'customer_notes': 'Доставка до 18:00'
}
response = requests.post(url, json=payload, headers=headers, timeout=10)
if response.status_code == 201:
order = response.json()
print(f"Заказ #{order['id']} успешно создан")
else:
print(f"Ошибка: {response.status_code}")
print(response.text)
При отправке JSON через post() обратите внимание на следующие моменты:
- Метод
post()возвращает объектResponse, содержащий результат запроса - Статус-код ответа доступен через атрибут
status_code - Содержимое ответа можно получить через методы
text(строка) илиjson()(парсинг JSON) - Для обработки ошибок используйте метод
raise_for_status(), который генерирует исключение при статус-кодах 4XX/5XX
Разница между параметрами json и data в requests.post()
Один из наиболее частых источников ошибок при работе с Requests — неправильное использование параметров json и data. Хотя оба параметра передают данные на сервер, механизм их работы существенно различается. 🧩
Ключевые различия:
| Характеристика | Параметр json | Параметр data |
|---|---|---|
| Тип входных данных | Python-словарь/список | Словарь/строка/байты |
| Сериализация | Автоматически сериализуется в JSON | Отправляется как есть или как form-data |
| Content-Type | application/json | application/x-www-form-urlencoded (по умолчанию) |
| Использование | REST API, требующие JSON | HTML-формы, multipart/form-data, произвольные данные |
| Вложенные структуры | Поддерживаются естественным образом | Требуют специальной обработки |
Использование json (рекомендуется для REST API):
# Правильный способ отправки JSON
data = {'name': 'John', 'age': 30, 'skills': ['Python', 'Flask', 'Django']}
response = requests.post('https://api.example.com/users', json=data)
# Content-Type: application/json
Использование data с ручной сериализацией (не рекомендуется):
# Менее удобный способ, требующий ручной сериализации
import json
data = {'name': 'John', 'age': 30, 'skills': ['Python', 'Flask', 'Django']}
headers = {'Content-Type': 'application/json'}
response = requests.post('https://api.example.com/users',
data=json.dumps(data),
headers=headers)
Использование data для form-encoded данных:
# Для отправки данных HTML-формы
form_data = {'username': 'john_doe', 'password': 'secret123'}
response = requests.post('https://example.com/login', data=form_data)
# Content-Type: application/x-www-form-urlencoded
Когда следует использовать параметр json:
- При работе с современными REST API
- Когда требуется отправка структурированных данных с вложенностью
- Если API требует заголовок Content-Type: application/json
Когда следует использовать параметр data:
- При отправке данных HTML-форм
- Для загрузки файлов через multipart/form-data
- Когда требуется полный контроль над форматом передаваемых данных
Мария Соколова, тимлид Python-разработки
В проекте интеграции с платежным шлюзом мы столкнулись с непредсказуемым поведением: большинство запросов проходило успешно, но примерно 5% завершалось ошибкой валидации. Анализ показал, что мы использовали параметр
dataи вручную сериализовали данные:PythonСкопировать кодpayload = json.dumps({ "amount": order.amount, "currency": "RUB", "description": order.description }) response = requests.post(payment_url, data=payload, headers=headers)Проблема крылась в том, что при ручной сериализации мы не учитывали особенности форматирования чисел с плавающей точкой. При переходе на параметр
json:PythonСкопировать кодpayload = { "amount": order.amount, "currency": "RUB", "description": order.description } response = requests.post(payment_url, json=payload, headers=headers)Ошибки прекратились, поскольку библиотека Requests корректно сериализует числа согласно спецификации JSON. Этот случай стал стандартным примером в нашей документации для новых разработчиков.
Обработка ответов API после отправки JSON запросов
После отправки JSON-запроса правильная обработка ответа API не менее важна, чем корректная отправка данных. Объект Response, возвращаемый методами библиотеки Requests, предоставляет богатый API для работы с результатами запроса.
Основные свойства и методы объекта Response:
- status_code — HTTP-статус ответа (200, 201, 400, 404, 500 и т.д.)
- headers — словарь с HTTP-заголовками ответа
- text — содержимое ответа в виде строки
- content — содержимое ответа в виде байтов
- json() — метод для парсинга JSON-ответа в Python-объекты
- raiseforstatus() — генерирует исключение для ошибочных статусов
- elapsed — время выполнения запроса
Пример комплексной обработки ответа:
import requests
from requests.exceptions import HTTPError, Timeout, ConnectionError, JSONDecodeError
def create_user(username, email):
url = 'https://api.example.com/users'
payload = {
'username': username,
'email': email
}
try:
# Отправляем запрос с таймаутом 5 секунд
response = requests.post(url, json=payload, timeout=5)
# Проверяем статус ответа
response.raise_for_status()
# Парсим JSON ответ
user_data = response.json()
print(f"Пользователь создан: ID={user_data['id']}")
return user_data
except HTTPError as http_err:
# Обработка ошибок HTTP (4XX, 5XX)
print(f"HTTP ошибка: {http_err}")
# Проверяем, вернул ли API подробности ошибки
try:
error_details = response.json()
print(f"Детали ошибки: {error_details}")
except JSONDecodeError:
print(f"Текст ошибки: {response.text}")
except Timeout:
print("Запрос превысил таймаут")
except ConnectionError:
print("Ошибка соединения с API")
except JSONDecodeError:
print(f"Не удалось распарсить JSON ответ: {response.text}")
except Exception as err:
print(f"Произошла ошибка: {err}")
return None
Особое внимание следует уделить обработке различных кодов состояния. Типичные статусы и их интерпретация:
- 2XX — Успешное выполнение
- 200 OK — запрос выполнен успешно
- 201 Created — ресурс успешно создан
- 204 No Content — успех, но нет данных в ответе
- 4XX — Ошибки клиента
- 400 Bad Request — неверный формат запроса или данных
- 401 Unauthorized — требуется аутентификация
- 403 Forbidden — доступ запрещен
- 404 Not Found — ресурс не найден
- 422 Unprocessable Entity — ошибка валидации данных
- 5XX — Ошибки сервера
- 500 Internal Server Error — внутренняя ошибка сервера
- 503 Service Unavailable — сервис временно недоступен
Идиоматический подход к обработке ответов API в Python включает:
- Использование контекста
try/exceptдля перехвата различных исключений - Вызов
raise_for_status()для автоматической проверки статуса - Обработку ошибок десериализации JSON
- Извлечение информации об ошибках из тела ответа при неудаче
Практические кейсы Python Requests JSON для интеграций
Рассмотрим несколько реальных сценариев использования JSON и Requests для типичных задач интеграции с внешними API. 🔄
Кейс 1: Авторизация и работа с защищенным API
import requests
import time
class APIClient:
def __init__(self, base_url, client_id, client_secret):
self.base_url = base_url
self.client_id = client_id
self.client_secret = client_secret
self.token = None
self.token_expires_at = 0
def _get_token(self):
"""Получение токена авторизации"""
if self.token and time.time() < self.token_expires_at – 60:
return self.token
auth_url = f"{self.base_url}/auth/token"
payload = {
"client_id": self.client_id,
"client_secret": self.client_secret,
"grant_type": "client_credentials"
}
response = requests.post(auth_url, json=payload)
response.raise_for_status()
token_data = response.json()
self.token = token_data["access_token"]
# Вычисляем время истечения (текущее время + срок действия в секундах)
self.token_expires_at = time.time() + token_data["expires_in"]
return self.token
def get_products(self, category=None, limit=50, offset=0):
"""Получение списка продуктов с опциональной фильтрацией"""
token = self._get_token()
headers = {"Authorization": f"Bearer {token}"}
endpoint = f"{self.base_url}/products"
params = {"limit": limit, "offset": offset}
if category:
params["category"] = category
response = requests.get(endpoint, headers=headers, params=params)
response.raise_for_status()
return response.json()
def create_order(self, customer_id, items, shipping_address):
"""Создание нового заказа"""
token = self._get_token()
headers = {
"Authorization": f"Bearer {token}",
"X-Idempotency-Key": str(int(time.time() * 1000)) # Защита от дублирования
}
payload = {
"customer_id": customer_id,
"items": items,
"shipping_address": shipping_address,
"created_at": time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime())
}
response = requests.post(
f"{self.base_url}/orders",
json=payload,
headers=headers
)
response.raise_for_status()
return response.json()
Кейс 2: Загрузка файла с JSON-метаданными
import requests
import os
import json
def upload_file_with_metadata(file_path, metadata, api_key):
"""
Загружает файл на сервер с сопроводительными JSON-метаданными
Args:
file_path (str): Путь к загружаемому файлу
metadata (dict): Метаданные файла (автор, теги и т.д.)
api_key (str): Ключ API для авторизации
Returns:
dict: Информация о загруженном файле
"""
upload_url = "https://api.fileservice.com/v1/upload"
# Подготавливаем метаданные как JSON-строку
metadata_json = json.dumps(metadata)
headers = {
"Authorization": f"ApiKey {api_key}",
"X-Request-ID": f"upload-{os.path.basename(file_path)}-{int(time.time())}"
}
# Подготавливаем multipart/form-data запрос
# Обратите внимание: метаданные передаются как часть формы, но в JSON-формате
files = {
"file": (os.path.basename(file_path), open(file_path, "rb")),
"metadata": ("metadata.json", metadata_json, "application/json")
}
response = requests.post(upload_url, headers=headers, files=files)
try:
response.raise_for_status()
return response.json()
except requests.exceptions.HTTPError as e:
print(f"Ошибка загрузки: {e}")
if response.text:
try:
error_details = response.json()
print(f"Детали: {error_details}")
except json.JSONDecodeError:
print(f"Ответ сервера: {response.text}")
raise
Кейс 3: Пагинация результатов API
import requests
from time import sleep
def fetch_all_items(api_url, token, page_size=100):
"""
Получает все элементы из API с пагинацией
Args:
api_url (str): URL API
token (str): Токен авторизации
page_size (int): Размер страницы
Returns:
list: Все полученные элементы
"""
headers = {"Authorization": f"Bearer {token}"}
all_items = []
page = 1
total_pages = None
while total_pages is None or page <= total_pages:
params = {
"page": page,
"per_page": page_size
}
response = requests.get(api_url, headers=headers, params=params)
# Обработка ограничения скорости запросов (rate limiting)
if response.status_code == 429:
# Извлекаем время ожидания из заголовков
retry_after = int(response.headers.get("Retry-After", 60))
print(f"Достигнут лимит запросов. Ожидание {retry_after} секунд...")
sleep(retry_after)
continue
response.raise_for_status()
data = response.json()
# Извлекаем метаданные пагинации
# Структура может отличаться в зависимости от API
if total_pages is None and "meta" in data:
total_pages = data["meta"]["total_pages"]
print(f"Всего страниц: {total_pages}")
# Извлекаем элементы
items = data.get("items", data.get("data", []))
all_items.extend(items)
print(f"Получена страница {page} из {total_pages or '?'}, элементов: {len(items)}")
# Переходим к следующей странице
page += 1
# Добавляем небольшую задержку, чтобы не перегружать API
sleep(0.5)
return all_items
Для работы с различными API можно выделить набор паттернов и оптимальных практик:
| Паттерн | Применение | Пример кода |
|---|---|---|
| Повторные попытки с экспоненциальной задержкой | Для нестабильных API с ошибками 5XX |
|
| Кэширование ответов | Для часто запрашиваемых неизменных данных |
|
| Идемпотентность запросов | Для предотвращения дублирования операций |
|
| Параллельные запросы | Для массовой загрузки данных |
|
При интеграции с внешними API помните о следующих рекомендациях:
- Создавайте классы-клиенты для инкапсуляции логики работы с API
- Используйте идемпотентные запросы для критических операций
- Реализуйте механизм повторных попыток для нестабильных соединений
- Следите за лимитами частоты запросов (rate limiting)
- Обрабатывайте ошибки на всех уровнях — сетевом, HTTP и бизнес-логики
Отправка JSON-данных с помощью Python Requests — это фундаментальный навык для любого разработчика, работающего с веб-сервисами. Овладев тонкостями использования параметров
jsonиdata, правильной обработки ответов и применения паттернов для типовых интеграционных задач, вы сможете создавать надежные и эффективные взаимодействия с API. Помните: хороший код для работы с API не только выполняет свою задачу, но и корректно обрабатывает исключительные ситуации, оптимизирует использование ресурсов и следует лучшим практикам отрасли. Внедрите описанные подходы в свой рабочий процесс, и интеграции с внешними системами станут гораздо более предсказуемыми и надежными.