Difference between data and json parameters in python requests package
To answer my own question, it appears my two examples above do the same thing and that using the json
parameter does indeed set the content-type
in the headers to application/json
. In my first example above using the data
parameter, the content-type
in the headers would need to be set manually.
What is the difference between the `data` and `json` named arguments with requests.post?
Passing a dict
to data
causes the dict
to be form-encoded, as though you were submitting a form on an HTML page; e.g., data={"example": "request"}
will be sent in the request body as example=request
. The json
keyword, on the other hand, encodes its argument as a JSON value instead (and also sets the Content-Type
header to application/json
).
Difference between data and params in Python requests?
params
form the query string in the URL, data
is used to fill the body of a request (together with files
). GET
and HEAD
requests have no body.
For the majority of servers accepting a POST
request, the data is expected to be passed in as the request body.
You need to consult the documentation for the specific API you are calling as to what they expect, but if you have to assume, assume you have to use data
.
what is the difference between data and params in requests?
According to the requests documentation:
- A
requests.post(url, data=data)
will make an HTTP POST request, and - A
requests.get(url, params=params)
will make an HTTP GET request
To understand the difference between the two, see this answer.
Here's how params can be used in a GET:
payload = {'key1': 'value1', 'key2': 'value2'}
r = requests.get('http://httpbin.org/get', params=payload)
print(r.text)
Which outputs
{
"args": {
"key1": "value1",
"key2": "value2"
},
[...]
"url": "http://httpbin.org/get?key1=value1&key2=value2"
}
Notice that the payload ended up in the query string of the URL. Since they ended up there, they are viewable by anyone who has access to the URL, which is why you shouldn't use query strings for sensitive data like passwords.
Here's how data can be used in a POST:
payload = 'foobar'
r = requests.post('http://httpbin.org/post', data=payload)
print(r.text)
Which outputs
{
"args": {},
"data": "foobar",
[...]
"url": "http://httpbin.org/post"
}
Notice how the POST data does not show up in the query strings, as they are transmitted through the body of the request instead.
Critique of this answer has pointed out that there are more options. I never denied such a thing in my original answer, but let's take a closer look.
The documentation examples always show:
- The params keyword used for GET, and
- The data keyword used for POST
But that doesn't mean they are mutually exclusive.
In theory you could mix the two together in a POST:
data = 'foobar'
params = {'key1': 'value1', 'key2': 'value2'}
r = requests.post('http://httpbin.org/post', params=params, data=data)
print(r.text)
Which outputs
{
"args": {
"key1": "value1",
"key2": "value2"
},
"data": "foobar",
[...]
"url": "http://httpbin.org/post?key1=value1&key2=value2"
}
But you cannot mix data into a GET:
data = 'foobar'
params = {'key1': 'value1', 'key2': 'value2'}
r = requests.get('http://httpbin.org/get', params=params, data=data)
print(r.text)
Outputs:
{
"args": {
"key1": "value1",
"key2": "value2"
},
[...]
"url": "http://httpbin.org/get?key1=value1&key2=value2"
}
Notice how the data field is gone.
HTTP requests and JSON parsing in Python
I recommend using the awesome requests library:
import requests
url = 'http://maps.googleapis.com/maps/api/directions/json'
params = dict(
origin='Chicago,IL',
destination='Los+Angeles,CA',
waypoints='Joplin,MO|Oklahoma+City,OK',
sensor='false'
)
resp = requests.get(url=url, params=params)
data = resp.json() # Check the JSON Response Content documentation below
JSON Response Content: https://requests.readthedocs.io/en/master/user/quickstart/#json-response-content
What is the difference between those two requests?
There is no "native dict" format in HTTP world.
The real difference is that requests
is too smart.
When using data=
in requests
, you are trying to post multipart/form-data
. In this case, a dict
will be unzipped into key-value pairs in form-data
format.
When using json=
in requests
, requests
will automatically json.dumps
your dict
into a raw byte string and set Content-Type
for you.
But in urllib
, it does nothing more than you give. You need to manually json.dumps
your dict
. So I believe the example you give is wrong. it should be like the following:
import urllib2
import json
req = urllib2.Request(url)
req.add_header('Content-Type', 'application/json')
resp = urllib2.urlopen(req, json.dumps(body)) #body from above
print resp.read()
Thanks for @t.m.adam's reminding.
How to POST JSON data with Python Requests?
Starting with Requests version 2.4.2, you can use the json=
parameter (which takes a dictionary) instead of data=
(which takes a string) in the call:
>>> import requests
>>> r = requests.post('http://httpbin.org/post', json={"key": "value"})
>>> r.status_code
200
>>> r.json()
{'args': {},
'data': '{"key": "value"}',
'files': {},
'form': {},
'headers': {'Accept': '*/*',
'Accept-Encoding': 'gzip, deflate',
'Connection': 'close',
'Content-Length': '16',
'Content-Type': 'application/json',
'Host': 'httpbin.org',
'User-Agent': 'python-requests/2.4.3 CPython/3.4.0',
'X-Request-Id': 'xx-xx-xx'},
'json': {'key': 'value'},
'origin': 'x.x.x.x',
'url': 'http://httpbin.org/post'}
JSON formatting for API requests, lines only needed if value is given in Python
Leave those fields out initially, then add them in an if
statement if needed.
test = {
"name": hostname,
"device_type": type,
"device_role": role,
"tenant": tenant,
"platform": platform,
"serial": chassis_serial,
"site": site,
"location": location,
"rack": rack,
"face": face,
"status": status,
"custom_fields": {}
}
if position:
test['position'] = position
if ilo:
test['custom_fields']['management_ip_address'] = str(ilo)
Related Topics
Differencebetween Join and Merge in Pandas
List All Base Classes in a Hierarchy of Given Class
Sampling Uniformly Distributed Random Points Inside a Spherical Volume
Default Filter in Django Admin
Python Command Line Input in a Process
Replace String Within File Contents
How to Run Python Script on Terminal
Search by Objectid in Mongodb with Pymongo
Putting Many Python Pandas Dataframes to One Excel Worksheet
Appending List But Error 'Nonetype' Object Has No Attribute 'Append'
Building Lxml for Python 2.7 on Windows
Getting List of Pixel Values from Pil