Python Dictionary From Lambda Github Webhook Event Failing to Lookup Key Value - python

I have an AWS Lambda that is sitting behind a API Gateway and taking POST requests from GitHub on Pull Requests. I'm trying to process the Payload so that I can make decisions based on the Pull Request status.
My issue is that I'm not able to get the dictionary key value. This is a slimmed down version of the dictionary that I'm getting in the Event variable of the Lambda (the payload from GitHub):
dict = {'version': 2.0, 'routeKey': 'POST /', 'body': '{"action": "synchronize","number": 1,"pull_request": {"url":"https://myurl.com"}'}
print(dict['body']['action'])
I need to get the value of the pull_request url. I get the following when I try to process the dictionary:
print(dict['version']) # 2.0
print(dict['body']['pull_request']['url']) #TypeError: string indices must be integers
Why is there a single quote in the dictionary that is preventing me from accessing keys and values?
How can I get the value of the pull request url from this key?

It is because dict['body'] is a string not a dictionary, you have to convert that to a dictionary before you can access.
Also it seems to be a malformed JSON string, missing a closing '}'
{"action": "synchronize","number": 1,"pull_request": {"url":"https://myurl.com"}
If you fix that you can then use json.loads
from json import loads
event = {'version': 2.0, 'routeKey': 'POST /', 'body': '{"action": "synchronize","number": 1,"pull_request": {"url":"https://myurl.com"}}'}
print(loads(event['body'])['pull_request']['url'])

Related

Extract key value from JSON using python NameError

I am creating a python script to extract values, Name from the JSON Key Details from the JSON result. Python error mentioned KeyError 'details[name]'. The JSON example is found below. The JSON is incomplete. JSON has other data which I am not going to put it here as it is confidential.
details: {'id': 5555, 'name': 'Timothy', 'Gender': 'Male'}
My Python script is shown below
print(json_data['details[name]'])
Error Message
print(json_data['details[name]'])
KeyError: 'details[name]'
I want to print the result
Timothy
What am I missing?
Assuming json_data is the name you've chosen for the entirety of the JSON object, you need provide a proper index for json_data in your print statement. Your current index is a string because you've captured your brackets inside of the apostrophes. The way you're indexing the JSON object is also incorrect.
JSON objects are essentially multidimensional dictionaries. The way you print the value of a value of a key is like this: print(dict["key"]["value"]).
Assuming the details key is also a string, the correct way to print the value of name from the key "details" is: print(json_data["details"]["name"]
do it one key at a time rather than trying to fit both the keys into one set of quotes as you originally had.
print(json_data['details']['name'])

POST request with nested JSON parameters malformed in request.POST

Inside integration tests, I try to make a POST request with a nested JSON parameter (this is just one of the approaches I tried):
test_function(admin_client):
admin_client.post(some_url,
json.dumps(some_nested_json),
content_type='application/json',
headers={'Content-type': 'application/json; charset=utf-8'})
I've also tried all sorts of different combinations for the parameters etc., everything I could find on the web, but I can't get the proper JSON output in the received request.JSON.
I get one of these three cases:
request.POST contains the first level of JSON plus the arrays of second level JSON keys
request.POST contains the first level of JSON plus an empty second level JSON
request.POST is empty, but request.body contains the whole nested JSON, in expected format
What am I missing here? I'm using Python 2.7.
This is expected behavior in django. Json requests are not in in request.POST but in request.body. You need to manually do json.loads(request.body) in your view.

Proper way of streaming JSON with Django

i have a webservice which gets user requests and produces (multiple) solution(s) to this request.
I want to return a solution as soon as possible, and send the remaining solutions when they are ready.
In order to do this, I thought about using Django's Http stream response. Unfortunately, I am not sure if this is the most adequate way of doing so, because of the problem I will describe below.
I have a Django view, which receives a query and answers with a stream response. This stream returns the data returned by a generator, which is always a python dictionary.
The problem is that upon the second return action of the stream, the Json content breaks.
If the python dictionary, which serves as a response, is something like {key: val}, after the second yield the returned response is {key: val} {key: val}, which is not valid Json.
Any suggestions on how to return multiple Json objects at different moments in time?
Try decoding with something like
for example
import json
json.dumps( {key: val} {key: val}, separators=('}', ':')) #check it
The solution is on the client side (eg: browser). You need to interpret the JSON result when it comes. By definition of a stream you never know when it finished, so everytime you receive some data on the client side, you need to interpret it as a self contain JSON message.

How to make requests.post not to wrap dict values in arrays in python?

I use python requests.post function to send json queries to my django app.
r = requests.post(EXTERNAL_SERVER_ADDRESS, data={'123':'456', '456':'789'})
But on the external server request.POST object looks like this:
<QueryDict: {'123': ['456'], '456': ['789']}>
Why does it happen? How can I just send a dict?
requests is not doing anything here. Presumably your receiving server is Django; that's just how it represents data from a request. request.POST['123'] would still give '456'.
You are sending a dict, Django transform this JSON in this QueryDict objetc automatically when it receives the message. If you want to parse it to an dict, do:
myDict = dict(queryDict.iterlists())

django nested body request not being set

I'm trying to make a request to the box api using python and django. I'm getting a 400 Entity body should be a correctly nested resource attribute name\\/value pair error.
My requests looks like:
requests.options(headers.kwargs['url'], headers=headers.headers,
data={'parent': {'id': 'xxxx'}, 'name': 'name.pdf'})
When I inspect the 400 request.body it contains 'parent=id&name=name.pdf' which leads me to believe I'm not setting the body properly
A curl works with the body
-d '{"name": "name.pdf", "parent": {"id": "xxxxx"}}'
Explicitly encode the dictionary to prevent form-encoding. Otherwise, it will be form-encoded as the way similar to urllib.urlencode (or urllib.parse.urlencode in Python 3.x).
import json
...
requests.options(
headers.kwargs['url'], headers=headers.headers,
data=json.dumps({'parent': {'id': 'xxxx'}, 'name': 'name.pdf'}))
In other word, instead of passing a dictionary, pass a string.
According to More complicated POST requests - Request documentation:
...
There are many times that you want to send data that is not
form-encoded. If you pass in a string instead of a dict, that data
will be posted directly.

Categories