How to convert strings from HTML request to Python objects with FastAPI - python

I am making my first API; any advice to improve my process is much appreciated.
I plan on passing JSON-like strings into the HTML request to this FastAPI microservice down there
#app.get("/create/{value}")
def createJSON(value:str):
person_json = value.strip()
fileName = person_json['Value']['0'] + person_json['Value']['1']
with open('%s.JSON','w') as writeFile:
writeFile.write(string)
return "Person has been created"
My HTTP request would look like this:
http://127.0.0.1:8000/create/{"Key":{"0":"name","1":"grad_year","2":"major","3":"quarter","4":"pronoun","5":"hobbies","6":"fun_fact","7":"food","8":"clubs","9":"res"},"Value":{"0":"adfasdfa","1":"adf'asd","2":"asd","3":"fads","4":"fa","5":"sdfa","6":"df","7":"asd","8":"fa","9":"df"}}
However, when doing this. The values passed are strings. Thus rendering the fileName portion of the code useless. How can I convert it to a Python dict? I have tried to use .strip(), but it did not help.

You're on the wrong track, Such a request should be essentially modeled as POST or a PUT request. That would allow you to send JSON in the body of the request and obtain it as a dict in python. You can see here
And even if you want to pass data in a GET request, there are query params
Coming back to the original doubt, you would have to use json.loads() to parse the json data and load it in a python dict then you can dump whatever file you like after that.

I'd recommend using the requests library
import requests
url = 'http://127.0.0.1:8000/create/'
params = dict(
name = 'Josh',
grad_year = '1987',
major = 'computer science',
quarter = '3'
)
resp = requests.get(url=url, params=params)
data = resp.json()
Then see here how to handle the JSON Response Content:
https://requests.readthedocs.io/en/master/user/quickstart/#json-response-content
The dict in the code I posted is different than the JSON you're trying to send through though. I assume you have a specific reason for having a "Key" array with the names than a "Value" array for the values of those specific names. But if not I'd recommend using a dictionary instead that way you can do things like:
fileName = person_json['name'] + person_json['grad-year']

Related

Is JSON data a string or a dictionary in Flask?

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!
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

How to access data from a post response in JSON format

I am trying to access a dictionary that has been returned after making a post to an API, but I am having difficulty formatting the data with JSON.
It seems to be returning the data as a dictionary but I receive the error 'list indices must be integers or slices, not str' which makes me believe that it is just returning a list that looks like a dictionary. I have tried using json.loads() and trying to access the data through lists but I can't seem to get it. The data I am trying to has multiple sub dictionaries/lists.
resp = post(url = endpoint_url, data = data, headers = headers)
data_for_process = resp.json()
print(data_for_process['pages']['keyValuePairs']['key'])
I expected the print statement to return the value for that specific key but I get the error instead.
Any help much appreciated.
you can use the json library of python
import json
import pprint
resp = post(url = endpoint_url, data = data, headers = headers)
resp_json = json.loads(resp.content)
pprint.pprint(resp_json) # to display the dict prettier

Automate data pull from App Annie API issue

I am needing to automate a daily pull of app Annie data reviews and land them in S3. With the below I am trying to see if I can just pull one days worth of data but am getting an error 'TypeError: expected string or buffer'. I am new to python, can someone explain what I am doing wrong or another way to accomplish what I am trying to do?
import json
import requests
url = 'https://api.appannie.com/v1.2/apps/ios/app/331177714/reviews?
start_date=2016-1-01&end_date=2016-6-26&countries=US'
key = 'Authorization: bearer 585e46.....'
response = requests.get(url,
headers = {'Authorization':'bearer 585e46.....'})
data = json.loads(response.json())
.json method you're using comes from requests object and it already converts string to proper json. So you can do two things
Convert to json with requests object method:
data = response.json()
Get text from your response and turn into json with Python json lib:
data = json.loads(response.text)

Flask-RESTful return does not need to be json.dumps()

I am trying to switch over my REST server from just Flask to Flask-RESTful.
What I am confused with is, I am using retrofit to read the data on the client, but on the first instance I need to use json.dumps(data) and the second I just need to return.
Can anyone explain this? In both bits of code data is a list
First example just Flask
data = []
for row in cur.fetchall():
out = {
"list_id": row[0],
"list_name": row[1]
}
data.append(out)
cur.close()
return json.dumps(data)
Second example Flask-RESTful
class UserLists(Resource):
def get(self, user_id):
results = Lists.query.filter(Lists.user_id == user_id).all()
data = [{'list_id': list_item.id, 'list_name': list_item.name} for list_item in results]
return data
Flask-RESTful takes care of encoding the response for you. It is not limited to returning just JSON, it will encode to supported formats based on the requested format from the client (set via the Accept request header).
See the Content Negotiation chapter to learn how to add format support other than the default JSON output.
As such, for a Flask-RESTful response you need to return a Python structure, not JSON-encoded data, as that would preclude producing, say, an XML or CSV response if you wanted to support such formats in the future.

Python, can someone explain this script to me?

I know nothing about Python but would like to clone this script with jquery using ajax post.
To do that i need to know what this script is doing in the first place.
import requests
import json
params = {'nearest': True, 'imageurl': img, 'timestamp':140000}
request = requests.post('http://example.com/api/upload/', data=params)
output = request.json()
print json.dumps(output['files'][0]['predicted_classes'])
Thanks. If something is unclear please comment and i'll clarify.
import requests
import json
above line imports two modules Request(contain methods for sending request to the server) and json(to serialise/deserialise data to json)
params = {'nearest': True, 'imageurl': img, 'timestamp':140000}
creating a dictionary with key value .here it is used to pass parameter
response= requests.post('http://example.com/api/upload/', data=params)
this is used to send Post resquest . here post is method in request module with parameters(Url,data_to_send)
output = response.json()
output has the response in json format
print json.dumps(output['files'][0]['predicted_classes'])
json dumps is used to convert to json format
This code does the following:
1) #First it imports the external modules.
2) #Next it defines params as a dictionary with 3 entries.
3) #Then it uses request libraries to get the file and transfigures "params" into a json object
4) #Lastly, the code prints the request.
To see the request you may need to use an image library to see what you gathered from the World Wide Web.

Categories