Using json argument instead of params argument to make POST request? (reddit API)

Screen Link: https://app.dataquest.io/m/110/challenge%3A-working-with-the-reddit-api/6/upvoting-a-comment

I tried to upvote a comment with https://old.reddit.com/dev/api#POST_api_vote endpoint. I created a code like below. Could someone explain why I have to use json key-word argument instead of params key-word argument? I am using python request library.
My Code:

parameter = {'dir':1,'id':'d16y4ry'}
post = requests.post('https://oauth.reddit.com/api/vote',params=parameter,headers=headers)
status = post.status_code

What I expected to happen:
I expected to get 201 for status. However, I got 400. Then, I replaced params with json and I got 201. Therefore, I guess that I should send the dictionary of parameters as json format. But, I haven’t find information making me certain with my guess in reddit API documentation.
Could someone explain why I have to use json key-word argument instead of params key-word argument?

1 Like

I would be thankful if someone can answer this question.

1 Like

hi @tokeihananda and @ashkan.ghanavati92

This may be an out and out lame post to differentiate between the two. Even I am not 100% clear about the two concepts.

But as a layman example: params go with the URL itself like a home address. (I take this way:
https://somevalidurlpart.com/#Q*hyg$/$%ghyst now this bold gibberish part is params. read about it here

Json here is the actual FedEx service, and the parameters defined in the dictionary format is the parcel that gets delivered to that URL which may or may not have the params included. Not sure how much this link would be helpful, but here it is

To answer this I tried this on the mission and the answer was still accpeted:

parameter = {'dir':1,'id':'d16y4ry'}
param_parameters = {}
post = requests.post('https://oauth.reddit.com/api/vote', params = param_parameters, json=parameter,headers=headers)
status = post.status_code

@joshdq / @Bruno / @hanqi Can you please help us all on this?

1 Like

Here are some practical considerations: https://stackoverflow.com/questions/25385559/rest-api-best-practices-args-in-query-string-vs-in-request-body

For finding hints from implementation side, let’s get to the source, learn some magic, learn the importing system.

Level 1 debugging

  1. In jupyter, do %pdoc requests.get and see from the popup it receives 3 inputs url,params, **kwargs
  2. %pdoc requests.post and see it receives 4 inputs url,data,json,**kwargs

You can stop here already and decide to follow what the API designers hint you, that basic use would not need **kwargs and if get, give params, if post give data + json. It also shows you which are (optional) inputs.

Another faster way is to put cursor anywhere on requests.post and press shift+tab (1/2/4x) and see the definitions appear. 1x for input names, 2x for description, 4x to get file location for level 2 debugging. Other relevant magics are %pfile, %pinfo, %pinfo2, %psource. %pfile provides the whole source code of the file the function appears in rather than shift+tab combinations which only gives information about that function.

Level 2 debugging

Now a new question is what is **kwargs doing in get and post. %pfile requests.get and enlarge popup to see whole file in text form. Alternatively if you have some IDE, get the file path, copy paste into terminal with open {filepath} and your terminal should open with your favourite editor which makes jumping around source code easier.
Maybe it’s a surprise (or not), %pfile requests.post leads you to the same file.
Ctrl+F return request and observe every function there is returning the same way by calling request. So request.get is just requests.request("method=get") and request.post is requests.request("method=post"), likewise for all other methods. The title of the file should give you a hint already. You would have seen from level1 debugging magics that filename is requests/api.py. This file exists to make the code of users of request library shorter and cleaner. It is an interface between users and developers. The developers under the hood work with a single requests.request() entrypoint, while users calling whatever methods all get funnelled into this 1 entrance so developers don’t have to maintain multiple functions.

Level 3 debugging

So what is requests.request, the single entry point doing? It returns

with sessions.Session() as session:
        return session.request(method=method, url=url, **kwargs)

so we look into sessions.Sessions().request. The way to do that step by step is to find the file: %pinfo requests.session , open the file, find Session class and the request method under it. You can see line 503,504

# Create the Request.
        req = Request(

Now what is Request? Note the capital R, its
from .models import Request, so you can open .models and continue the trace.

If you open the first file from IDE already, you could have skipped all the %pfile magics and jumped around IDE more easily by putting cursor on Request and Fn+12 to go level 4 debugging.

This may be slow, but to me its the most solid way to understand how something works. Sometimes you can even learn how something should work, that is not specified in docs. From reading the Exception(error messages) in the source code, you get a sense of what can go wrong. From the control flow leading to these exceptions, you understand the exact conditions under which these exceptions happen.

If you know pandas, here is another opportunity to exercise some source tracing skills, you can try to answer the title yourself before reading the article. https://medium.com/@hanqi_47643/whats-the-difference-between-pd-merge-and-df-merge-ab387bc20a2e

3 Likes

hi @hanqi

Thank you so much for taking time to give this detailed and informative answer for this query.

I would definitely refer and work on it in it’s entirety.

fore-warning: in case of doubts I will definitely bug you!

1 Like

Hi, I have the same problem but the solution here is a bit too technical for me.
do you understand it now?
can you please explain in layman terms when to use params = params and when to use json + params.
thanks.