Is JSON data a string or a dictionary in Flask?

Viewed 3099

This may be a silly question but I am really confused(I am a newbie). I am trying to make an API that accepts JSON as input and I am using Flask. The API takes POST method, so when a request comes along, it gets the JSON data from the body using

data = requests.get_json()

I expect data to be a string because, if I am not mistaken, JSON is nothing but a formatted string.

So, I do data = json.loads(data) But, my flask app crashes because it says data is a dictionary not a string. Of course, I can fix it by not using json.loads But it just bothers me and I wonder why I get a dictionary not a string.

Here is how I send test-requests, which seriously confuse me

1)

import requests
import pandas as pd
data = pd.read_csv('some.csv')
data = data.iloc[[0]].to_json(orient='records') // get the first row into json
res = requests.post(url, json=data) // I get a string in my Flask app.
import requests
data = {'name':'foo','age':99}
res = requests.post(url, json=data) // I get a dictionary in my Flask app.
const xhr = new XMLHttpRequest();
const json = {'name':'foo','age':99};
xhr.open("POST",url);
xhr.setRequestHeader("Content-Type","application/json");
xhr.send(JSON.stringify(json)); // Though stringified, I get a dictionary in my Flask app. Why?

I am not sure if you can see my confusion. In some cases, I get a dictionary, and in some other cases I get a string. So, I am confused and don't know how to design my API and handle the requests. Thank you in advance for your attention!

2 Answers

Pandas' DataFrame.to_json returns a string (str). Hence, in this code

data = df.to_json(orient='records')
res = requests.post(url, json=data)

data is actually a str object, and passing it to the json parameter of requests.post will encode that string as JSON again. See

response = requests.post(url, json={"foo": 1})
print(response.request.body)

response = requests.post(url, json='{"foo": 1}')
print(response.request.body)

Will print

b'{"foo": 1}'
b'"{\\"foo\\": 1}"'

What you must do, to send that JSON data correctly, is

data = df.to_json(orient='records')
response = requests.post(url, data=data.encode())

or actually convert the DataFrame to a dict

data = df.to_dict(orient='records')
response = requests.post(url, json=data)

JSON object is nothing but a dictionary in python and flask is framework written python
Accordingly, the json library exposes the dump() method for writing data to files. There is also a dumps() method (pronounced as “dump-s”) for writing to a Python string.
Simple Python objects are translated to JSON according to a fairly intuitive conversion.

Python          JSON
dict            object
list,tuple      array
str             string
int,long,float  number
True            true
False           false
None            null


so depending upon what is extracted from json python variable behaves accordingly,
like in first case
data = data.iloc[[0]].to_json(orient='records') data variable is nothing but a string,
so this is why res = requests.post(url, json=data) shows such behaviour here
In second Case
data = {'name':'foo','age':99} it's dictionary
so this why res = requests.post(url, json=data) shows such behaviour

Related