2013-05-10 16 views
8

Mam problemy podczas analizowania JSON-a z pythonem, a teraz utknąłem.
Problem polega na tym, że podmioty mojego JSON nie zawsze są takie same. JSON jest coś takiego:Parsowanie JSON-a z pythonem: puste pola

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

mogę przejść przez JSON, na przykład:

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

Problem pojawia się, ponieważ czasami, JSON nie wszystkie „pola”, na przykład, pola telephone, czasami brakuje, więc skrypt kończy się niepowodzeniem z KeyError, ponieważ w tym wpisie brakuje klucza telefon.
Moje pytanie: w jaki sposób mogę uruchomić ten skrypt, pozostawiając puste miejsce, w którym brakuje telefon? Próbowałem z:

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

ale myślę, że nie jest w porządku.

Odpowiedz

11

Zastosowanie dict.get zamiast []:

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

Lub po prostu:

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

get wróci drugi argument (domyślny, None) zamiast wychowywania KeyError gdy klucz nie został znaleziony .

0

Istnieje kilka przydatnych funkcji słownika, których można użyć do pracy z tym.

Po pierwsze, można użyć in przetestować, czy klucz istnieje w słowniku:

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

get może również być użyteczne; to pozwala określić wartość domyślną, jeśli klucz brakuje:

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

Poza tym, można spojrzeć średnia Biblioteki collections.defaultdict, ale to może być przesada.

8

Jeśli brakuje danych tylko w jednym miejscu, a następnie dict.get mogą być wykorzystywane do wypełnić brakujące brakującą wartość:

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

Jeśli problem jest bardziej powszechne, można mieć JSON parsera użyć defaultdict lub słownika niestandardowego zamiast zwykłego słownika. Na przykład, biorąc pod uwagę ciąg JSON:

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

analizować je z:

>>> 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'] 
'' 

Na marginesie, jeśli chcesz oczyścić-zapasowych zbiorów danych oraz egzekwowania konsystencję, nie jest dobrym narzędziem o nazwie Kwalify, który wykonuje walidację schematu na JSON (i na YAML);

+1

ładne, lubię to lepsze niż 'defaultdict 'ponieważ w metodzie' __missing__' można dodać trochę logiki, aby złapać potencjalny błąd. Z 'defaultdict' zawsze się boję, ponieważ nie otrzymam KeyError, gdy robię literówkę. –

0

Dwa sposoby.

Jedną z nich jest upewnienie się, że słowniki są standardowe, a gdy je przeczytasz, mają wszystkie pola. Drugi to ostrożność przy dostępie do słowników.

Oto przykład z upewniając się, że słowniki są standardowe:

__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 

Oto przykład bycia ostrożnym przy dostępie do słowników:

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