简体   繁体   中英

Create Dynamic Python Dictionary Reference Path

I'm having trouble dynamically creating a Python dictionary path to loop through and validate a value. Here's what I'd like to do:

Make API call using Requests 1.0 and store the JSON response in a dict.

response = requests.get(path/to/file.json).json()

The response object will be formatted as follows:

{   
"status": "OK",
"items": [
    {
        "name": "Name 1",
        "id": 0,
        "address":{
            "city": "New York",
        }
    },
    {
        "name": "Name 2",
        "id": 1,
        "address":{
            "city": "New York",
        }
    },
    {
        "name": "Name 3",
        "id": 2,
        "address":{
            "city": "New York",
        }
    }]
}

Send the response dict, field and value to a function for validation. The function would take the response object and append the field entry to it to define its path then validate against the value. So in theory it would be:

response[field] = value

The code that I wrote to do this was:

def dynamic_assertion(response, field, value):
        i = 0
        stations = "response['items']"
        count = len(response['items'])
        while i < count:
            path = '%s[%s]%s' % (stations, i, field)
            path = path.strip("")
            if path != value:
                print type(path)
                return False
            i += 1
        return True

dynamic_assertion(response, "['address']['city']", "New York")

I realize that once I create the path string it is no longer an object. How do I create this in a way that will allow me to keep the response object and append the reference path to traverse through? Is this even possible?!

I think you'd be better off avoiding a single path string in favor of a tuple or list of strings which represent the individual keys in the nested dictionaries. That is, rather than "['address']['city']" being your field argument, you'd pass ("address", "city") . Then you just need a loop to go through the keys and see if the final value is the correct one:

def dynamic_assertion(response, field, value):
    for item in response["items"]:
        for key in field:
            item = item[key] # go deeper into the nested dictionary
        if item != value:
            return False # raising an exception might be more Pythonic
    return True

Example output (given the response dict from the question):

>>> dynamic_assertion(response, ("address", "city"), "New York")
True
>>> dynamic_assertion(response, ("address", "city"), "Boston")
False
>>> response["items"][2]["address"]["city"] = "Boston" # make response invalid 
>>> dynamic_assertion(response, ("address", "city"), "New York")
False
>>> dynamic_assertion(response, ("address", "city"), "Boston")
False

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM