Home > Software engineering >  Save values from POST request of a list of dicts
Save values from POST request of a list of dicts

Time:04-12

I a trying to expose an API (if that's the correct way to say it). I am using Quart, a python library made out of Flask and this is what my code looks like:

async def capture_post_request(request_json):
    for item in request_json:
        callbackidd = item['callbackid']
        print(callbackidd)

@app.route('/start_work/', methods=['POST'])
async def start_work():
    content_type = request.headers.get('content-type')
    if (content_type == 'application/json'):
        request_json = await request.get_json()
        loop = asyncio.get_event_loop()
        loop.create_task(capture_post_request(request_json)) 
        body = "Async Job Started"
        return body
    else:
        return 'Content-Type not supported!'

My shcema looks like that:

[
{
    "callbackid": "dd",
    "itemid": "234r",
    "input": [
        {
            "type": "thistype",
            "uri": "www.uri.com"
        }
    ],
    "destination": {
        "type": "thattype",
        "uri": "www.urino2.com"
    }
},
{
    "statusCode": "202"
}

]

So far what I am getting is this error: "line 11, in capture_post_request callbackidd = item['callbackid'] KeyError: 'callbackid'"

I've tried so many stackoverflow posts to see how to iterate through my list of dicts but nothing worked. At one point in my start_work function I was using the get_data(as_text=True) method but still no results. In fact with the last method (or attr) I got: "TypeError: string indices must be integers"

Any help on how to access those values is greatly appreciated. Cheers.

CodePudding user response:

Your schema indicates there are two items in the request_json. The first indeed has the callbackid, the 2nd only has statusCode.

Debugging this should be easy:

async def capture_post_request(request_json):
    for item in request_json:
        print(item)
        callbackidd = item.get('callbackid')
        print(callbackidd) # will be None in case of the 2nd 'item'

This will print two dicts:

{
    "callbackid": "dd",
    "itemid": "234r",
    "input": [
        {
            "type": "thistype",
            "uri": "www.uri.com"
        }
    ],
    "destination": {
        "type": "thattype",
        "uri": "www.urino2.com"
    }
}

And the 2nd, the cause of your KeyError:

{
    "statusCode": "202"
}

I included the 'fix' of sorts already:

callbackidd = item.get('callbackid')

This will default to None if the key isn't in the dict.

Hopefully this will get you further!

Edit

How to work with only the dict containing your key? There are two options.

First, using filter. Something like this:

def has_callbackid(dict_to_test):
    return 'callbackid' in dict_to_test

list_with_only_list_callbackid_items = list(filter(has_callbackid, request_json))
# Still a list at this point! With dicts which have the `callbackid` key

Filter accepts some arguments:

  1. Function to call to determine if the value being tested should be filtered out or not.
  2. The iterable you want to filter

Could also use a 'lambda function', but it's a bit evil. But serves the purpose just as well:

list_with_only_list_callbackid_items = list(filter(lambda x: 'callbackid' in x, request_json))
# Still a list at this point! With dict(s) which have the `callbackid` key

Option 2, simply loop over the result and only grab the one you want to use.

found_item = None # default
for item in request_json:
    if 'callbackid' in item:
        found_item = item
        break # found what we're looking for, stop now
# Do stuff with the found_item from this point.
  • Related