Search code examples
pythonjsongeojson

Conditional checks for JSON key-value pairs being ignored


I am building a point feature class from a web call that returns JSON. The JSON is a bit sketchy in that sometimes keys do not exist in the record. I am trying to do this, once I have a valid JSON object:

#requests stuff above this

for i in jsonObj:
    try:
        if i['properties']['country']:
            country = i['properties']['country']
        else:
            country = 'UNK'
            print('Country name not found, using {}'.format(country))
    except KeyError, e:
        print('Key error: reason: {}'.format(str(e)))
        pass

#then do all the arcpy FC creation stuff

The result is a whole bunch of key errors with "reason: 'country'" and instead of building those rows with the generic 'country' value of 'UNK', it will simply ignore them and build the feature class, leaving out those points.

I have taken out the try and left it as a conditional check, but it fails at the first row that lacks a 'country' key.

In summary, I'm just trying to check if a key-value pair exists; if it doesn't, assign a generic value of 'UNK' to the country variable.

It seems like part of the problem might be that if i['properties']['countries'] is checking for a value, but not the existence of the key itself? How might I more efficiently check for the existence of the key?


I have read Check if a given key already exists in a dictionary and have modified my code to both of these, and neither yield the expected outcome:

for i in jsonObj:
    try:
        # get coordinates first
        if i['geometry']['coordinates']:
            ycoord = float(i['geometry']['coordinates'][1])
            xcoord = float(i['geometry']['coordinates'][0])
            if i['properties']['city'] in i:
                city = i['properties']['city']
            else:
                city = 'UNK'

            if i['properties']['country'] in i:
                country = i['properties']['country']
            else:
                country = 'UNK'

and

for i in jsonObj:
    try:
        # get coordinates first
        if i['geometry']['coordinates']:
            ycoord = float(i['geometry']['coordinates'][1])
            xcoord = float(i['geometry']['coordinates'][0])
            if 'city' in i:
                city = i['properties']['city']
            else:
                city = 'UNK'

            if 'country' in i:
                country = i['properties']['country']
            else:
                country = 'UNK'

I do have the 'properties' key in every record/dictionary, but whether I have a 'country' key is not guaranteed. Some rows in the json response have it, some rows don't


Solution

  • Your last try:

    if 'country' in i:
        country = i['properties']['country']
    else:
        country = 'UNK'
    

    was close, but you're managing a dict of dicts, and 'country' has better chance to be a key of the sub-dict, so the fix would be:

    if 'country' in i['properties']:
        country = i['properties']['country']
    else:
        country = 'UNK'
    

    or even better & shorter using get with a default value (I recommend that last one over the quickfix):

    country = i['properties'].get('country','UNK')