Почему тело запроса HTTP POST должно быть JSON, зарегистрированное в Python?
Я столкнулся с этой проблемой при игре с внешним API. Я отправлял данные своего тела в виде словаря прямо в запрос и получал 400 ошибок:
data = {
"someParamRange": {
"to": 1000,
"from": 100
},
"anotherParamRange": {
"to": True,
"from": False
}
}
Когда я добавил обертку json.dumps, он работает:
data = json.dumps({
"someParamRange": {
"to": 1000,
"from": 100
},
"anotherParamRange": {
"to": True,
"from": False
}
})
Я не совсем понимаю, почему это необходимо, поскольку словари и объекты JSON синтаксически идентичны. Может кто-нибудь помочь мне понять, что здесь происходит за кулисами?
Для полноты, вот мои заголовки:
headers = {'API-KEY': 'blerg', 'Accept-Encoding': 'UTF-8', 'Content-Type': 'application/json', 'Accept': '*/*', 'username': 'user', 'password': 'pwd'}
EDIT:
Я не упоминал об этом раньше, но теперь чувствую, что это может быть актуальным. Я использую библиотеку запросов Python, а другая публикация, похоже, предполагает, что вам никогда не придется кодировать параметры для объекта запроса: qaru.site/info/9731/...
"Независимо от того, не нужно ли снова и снова вводить параметры GET/POST, он просто вводит словарь в качестве аргумента и имеет смысл идти".
Кажется, что сериализация не нужна?
Мой объект запроса:
response = requests.post(url, data=data, headers=headers)
Ответы
Ответ 1
Очевидно, ваш API требует JSON-кодированных и неформатированных данных. Когда вы передаете dict
в качестве параметра data
, данные кодируются в форме. Когда вы передаете строку (например, результат json.dumps
), данные не закодированы в форме.
Рассмотрим эту цитату из документации запросов:
Как правило, вы хотите отправить некоторые данные, закодированные в форме, - как HTML-форму. Для этого просто передайте словарь в аргумент данных. Ваш словарь данных будет автоматически закодирован в форму при запросе.
Существует много раз, когда вы хотите отправить данные, которые не закодированы в форме. Если вы передадите строку вместо dict, эти данные будут опубликованы напрямую.
Например, API-интерфейс GitHub v3 принимает данные POST/PATCH с кодировкой JSON:
>>> import json
>>> url = 'https://api.github.com/some/endpoint'
>>> payload = {'some': 'data'}
>>> r = requests.post(url, data=json.dumps(payload))
Refs:
Ответ 2
Хотя они кажутся синтаксическими, существует разница: JSON представляет собой строковое представление сериализованного объекта; в этом случае Python dict. В этом примере вам нужно отправить сериализованные данные в форме строки, и поэтому для выполнения сериализации необходимо использовать json.dumps.
изменить
Как было предложено в комментариях к вопросу, это относится к используемому API, но тем не менее сериализация должна выполняться где-то по пути отправки объекта по проводу.