Python request module sends JSON string instead of x-www-form-urlencoded param string

I was under the impression that POSTS using the x-www-form-urlencoded specs should send a URL-encoded string in the body of the post. However, when I do this,

data = json.dumps({'param1': 'value1', 'param2': 'value2'})
Requests.post(url, data=data)

      

The request body on the receiving end looks like this:

{"param1": "value1", "param2": "value2"}

      

But I was expecting to get this

param1=value1&param2=value2

      

How can I get requests to submit data in the second form?

+12


source to share


2 answers


The reason you are getting JSON is because you are explicitly calling json.dumps

to generate a JSON string. Just don't do this and you won't get a JSON string. In other words, change your first line to this:

data = {'param1': 'value1', 'param2': 'value2'}

      

As the docs explain , if you pass a dict as a value data

, it will be encoded in the form, and if you pass in a string, it will be sent as is.


For example, in one terminal window:

$ nc -kl 8765

      



In another:

$ python3
>>> import requests
>>> d = {'spam': 20, 'eggs': 3}
>>> requests.post("http://localhost:8765", data=d)
^C
>>> import json
>>> j = json.dumps(d)
>>> requests.post("http://localhost:8765", data=j)
^C

      

In the first terminal, you will see that the first request body is (and Content-Type application/x-www-form-urlencoded

):

spam=20&eggs=3

      

... while the second is this (and has no Content-Type):

{"spam": 20, "eggs": 3}

      

+32


source


It's important to add that this doesn't work for nested JSON So if you have



# Wrong
data = {'param1': {'a':[100, 200]},
        'param2': 'value2',
        'param3': False}

# You have to convert values into string:
data = {'param1': json.dumps({'a':[100, 200]}),
        'param2': 'value2',
        'param3': json.dumps(False)}

      

0


source







All Articles