2017-01-16 1 views
1

In einem Wort, was ich suche, ist mehr oder weniger ein Äquivalent von SQL nvl() in Python.Wie kann ich eine nvl() tun, um Fehler von nicht vorhandenen JSON-Element zu vermeiden?

Weitere Informationen:

Ich habe eine Schleife Daten aus einer Liste von jsons abruft. Sie sehen alle gleich aus, aber einige von ihnen fehlen einige der Dinge, die ich abrufe. Wenn ich versuche, data['movie']['boxOffice'][0]['admissionCount'] zu erhalten, und es nicht in JSON ist, erhalte ich einen Fehler (Anmerkung: das kann sein, weil 'accessCount' nicht existiert, oder weil 'boxOffice' nicht existiert).

Um dies zu umgehen, ist hier, was für den Moment, wo ich so mache:

try: 
    admissionCount = data['movie']['boxOffice'][0]['admissionCount'] 
except: 
    admissionCount = '' 

Es funktioniert gut, aber ich habe ~ 50 Felder, die Möglichkeit zu überprüfen, ...

Ich versuchte es drehen in eine Funktion:

Und dann erkannte, dass es dumm war, und natürlich bekomme ich einen Fehler.

Wie kann ich vermeiden, 50 try/except Blöcke zu machen?

Dank

Antwort

1

Sie eine Funktion sicher in diese Struktur verwenden können, um zu graben:

def get_deep_dict(a_dict, keys): 
    value = a_dict 
    for key in keys: 
     try: 
      value = value.get(key) 
     except AttributeError: 
      try: 
       value = value[key] 
      except (IndexError, TypeError): 
       return None 
    return value 

Testdaten und Testfälle: es

data = dict(movie=dict(boxOffice=[dict(admissionCount=5)])) 
admissionCount = data['movie']['boxOffice'][0]['admissionCount'] 

assert admissionCount == get_deep_dict(
    data, ('movie','boxOffice', 0, 'admissionCount')) 

assert None == get_deep_dict(
    data, ('movie','boxOffices', 0, 'admissionCount')) 

assert None == get_deep_dict(
    data, ('movie','boxOffice', 1, 'admissionCount')) 
+0

richtige Idee, aber nicht ganz: Wenn '[0]' am Eingang arbeitet, war es ein Array, kein Wörterbuch. Daher ist '.get()' nicht genug. – dhke

+0

Danke, aktualisiert –

1

Während können wir auch tun es in einer allgemeinen Weise:

def get_default(base, *keys, **kwargs): 
    sentinel = kwargs.get('sentinel', None) 
    cur = base 
    for key in keys: 
     try: 
      cur = cur[key] 
     except (KeyError, IndexError): 
      return sentinel 
    return cur 

data = { 
    'movie': { 
     'boxOffice': [ 
      {'admissionCount': 10}, 
      {'admissionCount': 20}, 
     ] 
    } 
} 

Dies setzt voraus, dass jedes Unterobjekt die richtigen __getitem__() implementiert, die KeyError und IndexError nicht für andere nicht zugängliche (Teil-) Elemente anheben. Die dict- und list-Objekte, die vom standardmäßigen JSON-Decoder zurückgegeben werden, tun dies, aber achten Sie auf benutzerdefinierte Objekte.

print get_default(data, 'movie', 'boxOffice', 0, 'admissionCount') 
>>> 10 
print get_default(data, 'movie', 'boxOffice', 1, 'admissionCount') 
>>> 20 
print get_default(data, 'movier') 
>>> None 
print get_default(data, 'movie', 'boxOffice') 
>>> None 
print get_default(data, 'movie', 'boxOffice', 3) 
>>> None 
print get_default(data, 'movie', 'boxOffice', 3, 'admisssionCount', sentinel=-1) 
>>> -1 
1

können Sie die .get() Methode mit Standard für dicts verwenden

dict = {"a" : 1} 
dict.get("a") # return 1 
dict.get("b") # return None 
dict.get("b", "default_obj") # return default_obj 
Verwandte Themen