user1772250
user1772250

Reputation: 379

Passing both dict and json to a url

I have to use a webservice endpoint that needs both JSON and non-json in the query and I don't know how to do it with the requests package. the same code provided has http.client in it, and I don't have access to that package in this project for unrelated reasons

The example code is:

import http.client

conn=http.client.HTTPSConnection('some.url')
payload="{\"some_json_dict_key\": \"some_json_dict_value\"}"
headers={'content-type': "application/json", 'accept': "application/json"}
conn.request("POST", "/someEndpoint?param1=value_of_param1", payload, headers)
res = conn.getresponse()
data = res.read().decode('utf-8')

The code i have tried which doesnt work:

import requests

headers={'content-type': "application/json", 'accept': "application/json"}
params={'param1': 'value_of_param1'}
json_payload = "{\"some_json_dict_key\": \"some_json_dict_value\"}"
url = 'https://some.url/someEndpoint'
response = requests.post(url, headers=headers, data=params, json=json_payload)

however that doesn't seem to work i get the exception

{'httpMessage': 'Bad Request', 'moreInformation': 'The body of the request, which was expected to be JSON, was invalid, and could not be decoded. The start of an object { or an array [ was expected.'}

Upvotes: 1

Views: 1318

Answers (2)

alexis
alexis

Reputation: 50220

You must realize that a POST request can pass information in two places: In the body (data) of the request, and in the URL string (the request parameters, like a GET request does). In the example you didn't fully emulate, the parameters are in the URL string, and the body, according to the error message you got back, must consist of a single JSON object. Therefore, use the params dictionary for the URL parameters, like this:

response = requests.post(url, headers=headers, params=params, data=json_payload)

That ought to do it, unless there are other details to take care of.

Upvotes: 0

Jean-François Fabre
Jean-François Fabre

Reputation: 140286

According to the documentation:

Instead of encoding the dict yourself, you can also pass it directly using the json parameter (added in version 2.4.2) and it will be encoded automatically:

>>> url = 'https://api.github.com/some/endpoint'
>>> payload = {'some': 'data'}

>>> r = requests.post(url, json=payload)

but you're passing a string into the json parameter (I admit that the error message could be clearer). All other parameters are json/dict objects. Make json_payload an actual dictionary.

json_payload = {"some_json_dict_key": "some_json_dict_value"}  # real dictionary, not a json string
url = 'https://some.url/someEndpoint'
response = requests.post(url, headers=headers, data=params, json=json_payload)

Upvotes: 1

Related Questions