2013-05-10 16 views
8

Ich habe Probleme beim Parsen eines JSON mit Python, und jetzt bin ich fest.
Das Problem ist, dass die Entitäten meines JSON nicht immer gleich sind. Die JSON ist so etwas wie:Parsen von JSON mit Python: leere Felder

"entries":[ 
{ 
"summary": "here is the sunnary", 
"extensions": { 
    "coordinates":"coords", 
    "address":"address", 
    "name":"name" 
    "telephone":"123123" 
    "url":"www.blablablah" 
}, 
} 
] 

Ich kann die JSON bewegen, zum Beispiel durch:

for entrie in entries: 
    name =entrie['extensions']['name'] 
    tel=entrie['extensions']['telephone'] 

Das Problem kommt, weil manchmal, wird die JSON nicht alle „Felder“, zum Beispiel haben, das Feld telephone fehlt manchmal, daher schlägt das Skript mit KeyError fehl, weil der Schlüssel Telefon in diesem Eintrag fehlt.
Also, meine Frage: Wie könnte ich dieses Skript ausführen, eine leere Stelle, wo Telefon fehlt? Ich habe versucht, mit:

if entrie['extensions']['telephone']: 
    tel=entrie['extensions']['telephone'] 

aber ich denke nicht in Ordnung ist.

Antwort

11

Verwenden dict.get statt []:

entries['extensions'].get('telephone', '') 

Oder einfach:

entries['extensions'].get('telephone') 

get wird das zweite Argument zurückgeben (default, None) stattdessen eine KeyError zu heben, wenn der Schlüssel nicht gefunden wird .

0

Es gibt mehrere nützliche Wörterbuchfunktionen, mit denen Sie damit arbeiten können.

First off, können Sie in verwenden, um zu testen, ob ein Schlüssel in einem Wörterbuch vorhanden ist:

if 'telephone' in entrie['extensions']: 
    tel=entrie['extensions']['telephone'] 

get könnte auch nützlich sein; ermöglicht es Ihnen, einen Standardwert angeben, wenn der Schlüssel fehlt:

tel=entrie['extensions'].get('telephone', '') 

Darüber hinaus werden Sie in der Standard-Bibliothek aussehen könnte collections.defaultdict, aber das könnte zu viel des Guten.

8

Wenn die Daten nur an einer Stelle fehlen, dann kann dict.get verwendet werden, um zu füllen, um den fehlenden Wert fehlt:

tel = d['entries'][0]['extensions'].get('telelphone', '') 

Wenn das Problem weiter verbreitet ist, können Sie die JSON-Parser verwendet eine haben defaultdict oder benutzerdefiniertes Wörterbuch anstelle eines regulären Wörterbuchs. Um zum Beispiel die JSON-String gegeben:

json_txt = '''{ 
    "entries": [ 
     { 
      "extensions": { 
       "telephone": "123123", 
       "url": "www.blablablah", 
       "name": "name", 
       "coordinates": "coords", 
       "address": "address" 
      }, 
      "summary": "here is the summary" 
     } 
    ] 
}''' 

Parse es mit:

>>> class BlankDict(dict): 
     def __missing__(self, key): 
      return '' 

>>> d = json.loads(json_txt, object_hook=BlankDict) 

>>> d['entries'][0]['summary'] 
u'here is the summary' 

>>> d['entries'][0]['extensions']['color'] 
'' 

Als Seite beachten, wenn Sie Ihre Datensätze bereinigen wollen und durchzusetzen Konsistenz, gibt es ein feines Tool namens Kwalify, die Schema-Validierung für JSON (und für YAML) durchführt;

+1

Nizza, Gefällt mir besser als 'defaultdict 'weil innerhalb der' __missing__' Methode man in der Lage wäre, etwas Logik hinzuzufügen, um einen möglichen Fehler zu finden. Mit 'defaultdict' schaue ich immer zusammen, weil ich keinen KeyError bekomme, wenn ich einen Tippfehler mache. –

0

Zwei Möglichkeiten.

Eine ist, um sicherzustellen, dass Ihre Wörterbücher Standard sind, und wenn Sie sie lesen, haben sie alle Felder. Der andere ist vorsichtig beim Zugriff auf die Wörterbücher.

Hier ist ein Beispiel dafür, dass Ihre Wörterbücher Standard sind:

__reference_extensions = { 
    # fill in with all standard keys 
    # use some default value to go with each key 
    "coordinates" : '', 
    "address" : '', 
    "name" : '', 
    "telephone" : '', 
    "url" : '' 
} 

entrie = json.loads(input_string) 
d = entrie["extensions"] 
for key, value in __reference_extensions: 
    if key not in d: 
     d[key] = value 

Hier ist ein Beispiel darauf achten, wenn die Wörterbücher zugreifen:

for entrie in entries: 
    name = entrie['extensions'].get('name', '') 
    tel = entrie['extensions'].get('telephone', '')