Flask JSON Parsing - python

def api_all():
return jsonify(data)
#app.route('/api/', methods=['GET'])
def api_id():
if('id' in request.args and 'key' in request.args):
id = int(request.args['id'])
key = str(request.args['key'])
else:
return "Error: Missing argument."
results = []
for user in data["users"]: # Error from here
print(user)
if(user['id'] == id and user['key'] == key):
results.append(user)
return jsonify(results)
app.run()
There is my main code.
"users": [
{
"id":"0",
"name":"Jane",
"balance":"100$",
"key":"byt3dsz69pl0hmb"
},
{
"id":"1",
"name":"John",
"balance":"100$",
"key":"z0apdio4bvn549e"
}
]
}
Here is data.json or, the data variable. I cannot get this to work, I get the following error:
TypeError: '_io.TextIOWrapper' object is not subscriptable
I am building a basic api to get account balances, this is juts for educational purposes so it does not have to be secure. Any help would be greatly appreciated I have used flask before but I can never get my head around how JSON works with python, I find it quite hard to understand.

That code snippet converts id from the request to an int, but the value of the id key in the JSON is a string. Since
>>> 1 == "1"
False
>>>
you'll to make the types match before you can compare them.

Related

Error when trying to access nested objects from API response

I am finding that I keep getting errors when accessing objects that are nest in three other objects.
The following is an example of one of the entities returned when accessing the API:
entity {
id: "000069R"
trip_update {
trip {
trip_id: "064650_R..S"
route_id: "R"
start_time: "10:46:30"
start_date: "20220902"
nyct_trip_descriptor {
train_id: "1R 1046+ CTL/95S"
direction: SOUTH
}
}
stop_time_update {
stop_id: "G08S"
arrival {
time: 1662129990
}
departure {
time: 1662129990
}
nyct_stop_time_update {
scheduled_track: "D1"
actual_track: "D1"
}
}
}
This is my code:
import gtfs_realtime_pb2
import urllib.request
trainsets=[
['a','c','e'],
['b','d','f', 'm'],
['g'],
['j','z'],
['n','q','r', 'w'],
['l'],
['1','2','3','4','5','6','7']
]
set_number=0
# get the train from user and find the corresponding trainset
char = input("What train are you looking for? ")
char = char.lower()
for sets in trainsets:
if char in sets:
print('Found it!')
set_number = trainsets.index(sets)
# form string from the values in specified list
desired_trainset= ''.join(trainsets[set_number])
# Communicate with the api
feed = gtfs_realtime_pb2.FeedMessage()
response = urllib.request.Request(f'https://api-endpoint.mta.info/Dataservice/mtagtfsfeeds/nyct%2Fgtfs-{desired_trainset}')
response.add_header("x-api-key", '<API KEY HERE>')
feed.ParseFromString(urllib.request.urlopen(response).read())
# access specific info from the api
for entity in feed.entity:
if entity.HasField('trip_update'):
#! ERROR: AttributeError: nyct_trip_descriptor
print(entity.trip_update.trip.nyct_trip_descriptor.direction)
#! ERROR: AttributeError: 'google._upb._message.RepeatedCompositeContainer' object has no attribute 'arrival'
print(entity.trip_update.stop_time_update.arrival.time)
The last two print statements are where I keep getting an error. I can access start_time and start_date
or stop_id from the entity just fine, but I keep getting an error when trying to access objects inside other objects.
Using:
Python: 3.10.6
Windows: 11
I've asked a couple of my friends and they don't see the error.
Thank you for helping.
EDIT:
Someone requested to print the entity before the error. This is one of the responses I get back from the data when I do the following code:
print(entity.trip_update.trip)
#response I get back
trip_id: "006600_R..N"
route_id: "R"
start_time: "01:06:00"
start_date: "20220903"
nyct_trip_descriptor {
train_id: "1R 0106 95S/WHL"
}
Someone commented that the nyct_trip_descriptor is an optional field, and after rereading the documentation i confirmed that it is optional but I'm not sure how to proceed further and whether or not that is the reason why I'm getting this error. Thank you for helping.
Edit:
I've done the following to return a default value when 'nyct_trip_descriptor' is missing:
nyct_trip_descriptor = getattr(entity.trip_update.trip, 'nyct_trip_descriptor', 'not found')
print(nyct_trip_descriptor)
This didn't work since all the entities I got from the API just stated 'not found', but when printing just the entity 'nyct_trip_descriptor' is present as seen in the first code snippet.

Printing dictionary from inside a list puts one character on each line

Yes, yet another. I can't figure out what the issue is. I'm trying to iterate over a list that is a subsection of JSON output from an API call.
This is the section of JSON that I'm working with:
[
{
"created_at": "2017-02-22 17:20:29 UTC",
"description": "",
"id": 1,
"label": "FOO",
"name": "FOO",
"title": "FOO",
"updated_at": "2018-12-04 16:37:09 UTC"
}
]
The code that I'm running that retrieves this and displays it:
#!/usr/bin/python
import json
import sys
try:
import requests
except ImportError:
print "Please install the python-requests module."
sys.exit(-1)
SAT_API = 'https://satellite6.example.com/api/v2/'
USERNAME = "admin"
PASSWORD = "password"
SSL_VERIFY = False # Ignore SSL for now
def get_json(url):
# Performs a GET using the passed URL location
r = requests.get(url, auth=(USERNAME, PASSWORD), verify=SSL_VERIFY)
return r.json()
def get_results(url):
jsn = get_json(url)
if jsn.get('error'):
print "Error: " + jsn['error']['message']
else:
if jsn.get('results'):
return jsn['results']
elif 'results' not in jsn:
return jsn
else:
print "No results found"
return None
def display_all_results(url):
results = get_results(url)
if results:
return json.dumps(results, indent=4, sort_keys=True)
def main():
orgs = display_all_results(KATELLO_API + "organizations/")
for org in orgs:
print org
if __name__ == "__main__":
main()
I appear to be missing a concept because when I print org I get each character per line such as
[
{
"
c
r
e
a
t
e
d
_
a
t
"
It does this through to the final ]
I've also tried to print org['name'] which throws the TypeError: list indices must be integers, not str Python error. This makes me think that org is being seen as a list rather than a dictionary which I thought it would be due to the [{...}] format.
What concept am I missing?
EDIT: An explanation for why I'm not getting this: I'm working with a script in the Red Hat Satellite API Guide which I'm using to base another script on. I'm basically learning as I go.
display_all_results is returning a string since you are doing json.dumps in json.dumps(results, indent=4, sort_keys=True), which converts the dictionary to a string (you are getting that dictionary from r.json() in get_json function)
You then end up iterating over the characters of that string in main, and you see one character per line
Instead just return results from display_all_results and the code will work as intended
def display_all_results(url):
#results is already a dictionary, just return it
results = get_results(url)
if results:
return results
Orgs is a result of json.dump which produces a string. So instead of this code:
for org in orgs:
print(org)
replace it with simply:
#for org in orgs:
print(orgs)

How to use a value in a JSON file within an if statement

I'm trying to create an if statement based on the value from an API I'm using. This API contains a status code value, "status". if this is 404 (or others) I want to return an error, else carry on.
An example of the JSON:
{
"data": {
"test_index": {
"test_a": [...], // 429 items
"test_b": [...] // 182 items
}
},
"status": 200
}
When running the code below:
import json
import urllib.request as ur
API = ur.urlopen('https://example.com')
data = json.loads(API.read())
if data['status'][0] == 404:
print("404")
else:
print("Not 404")
I get the following error:
TypeError: 'int' object is not subscriptable
Which is referring to line 7, the if statement.
How do I convert this JSON value to something I can work with?
data['status'] is an integer, and you cannot subscript an integer with an index, like you do for a list, Change your code as follows.
if data['status'] == 404:
print("404")
else:
print("Not 404")

Why am I getting a Runtime.MarshalError when using this code in Zapier?

The following code is giving me:
Runtime.MarshalError: Unable to marshal response: {'Yes'} is not JSON serializable
from calendar import monthrange
def time_remaining_less_than_fourteen(year, month, day):
a_year = int(input['year'])
b_month = int(input['month'])
c_day = int(input['day'])
days_in_month = monthrange(int(a_year), int(b_month))[1]
time_remaining = ""
if (days_in_month - c_day) < 14:
time_remaining = "No"
return time_remaining
else:
time_remaining = "Yes"
return time_remaining
output = {time_remaining_less_than_fourteen((input['year']), (input['month']), (input['day']))}
#print(output)
When I remove {...} it then throws: 'unicode' object has no attribute 'copy'
I encountered this issue when working with lambda transformation blueprint kinesis-firehose-process-record-python for Kinesis Firehose which led me here. Thus I will post a solution to anyone who also finds this questions when having issues with the lambda.
The blueprint is:
from __future__ import print_function
import base64
print('Loading function')
def lambda_handler(event, context):
output = []
for record in event['records']:
print(record['recordId'])
payload = base64.b64decode(record['data'])
# Do custom processing on the payload here
output_record = {
'recordId': record['recordId'],
'result': 'Ok',
'data': base64.b64encode(payload)
}
output.append(output_record)
print('Successfully processed {} records.'.format(len(event['records'])))
return {'records': output}
The thing to note is that the Firehose lambda blueprints for python provided by AWS are for Python 2.7, and they don't work with Python 3. The reason is that in Python 3, strings and byte arrays are different.
The key change to make it work with lambda powered by Python 3.x runtime was:
changing
'data': base64.b64encode(payload)
into
'data': base64.b64encode(payload).decode("utf-8")
Otherwise, the lambda had an error due to inability to serialize JSON with byte array returned from base64.b64encode.
David here, from the Zapier Platform team.
Per the docs:
output: A dictionary or list of dictionaries that will be the "return value" of this code. You can explicitly return early if you like. This must be JSON serializable!
In your case, output is a set:
>>> output = {'Yes'}
>>> type(output)
<class 'set'>
>>> json.dumps(output)
Object of type set is not JSON serializable
To be serializable, you need a dict (which has keys and values). Change your last line to include a key and it'll work like you expect:
# \ here /
output = {'result': time_remaining_less_than_fourteen((input['year']), (input['month']), (input['day']))}

Can we return Data in JSON format in flask using Neo4j queries?

I want to return data in JSON format from Flask method. My Code is written in Flask and Neo4j is used for storing Data.
As of now, my code is:
result = session.run("MATCH (p:Person {name:$username})-[:PURCHASED]->(:Product)<-[:PURCHASED]-(p2:Person)-[:PURCHASED]->(pd2:Product)"
"WHERE NOT (p)-[:PURCHASED]->(pd2)"
"RETURN pd2.title as product_title, pd2.description as product_details" , username=username)
for record in result:
print("%s %s" % (record["product_title"], record["product_details"]))
return 'Loop Entered'
return 'OK'
I tried using 'jsonify' as below but got Type error as : TypeError: ('product_title', 'product_details')
return jsonify([record[("product_title","product_details")] for record in result])
Please let me know what I am missing here.
Maybe you wanted to do this:
return jsonify({record["product_title"]: record["product_details"] for record in result})
or even
return jsonify([
{
"product_title": record["product_title"],
"product_details": record["product_details"],
}
for record in result
])
?
You can access only one key at a time when using dict type in Python

Categories