2013-05-10 13 views
8

Ho problemi durante l'analisi di un JSON con python e ora sono bloccato.
Il problema è che le entità del mio JSON non sono sempre le stesse. Il JSON è qualcosa di simile:Parsing JSON con python: campi vuoti

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

posso spostare attraverso il JSON, ad esempio:

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

Il problema nasce perché a volte, il JSON non ha tutti i "campi", per esempio, il campo telephone, a volte manca, quindi, lo script ha esito negativo con KeyError, poiché in questa voce manca la chiave .
Quindi, la mia domanda: come posso eseguire questo script, lasciando uno spazio vuoto dove telefono manca? Ho provato con:

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

ma penso che non è ok.

risposta

11

Uso dict.get invece di []:

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

Oppure, semplicemente:

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

get restituirà il secondo argomento (di default, None) invece di sollevare un KeyError quando non si trova la chiave .

0

Esistono diverse utili funzioni del dizionario che è possibile utilizzare per lavorare con questo.

Prima di tutto, è possibile utilizzare in per verificare l'esistenza o meno di una chiave in un dizionario:

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

get potrebbe anche essere utile; esso consente di specificare un valore predefinito se manca la chiave:

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

Al di là di questo, si potrebbe esaminare la libreria standard del collections.defaultdict, ma che potrebbe essere eccessivo.

8

Se i dati non è presente in un solo posto, quindi dict.get può essere utilizzato per compilare manca il valore mancante:

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

Se il problema è più diffuso, si può avere la JSON parser uso di un defaultdict o dizionario personalizzato al posto di un dizionario normale. Ad esempio, data la stringa JSON:

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

Parse con:

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

Come nota a margine, se si desidera pulire-up dei set di dati e far rispettare la coerenza, v'è un ottimo strumento chiamato Kwalify che esegue la convalida dello schema su JSON (e su YAML);

+1

bello, mi piace questo meglio allora 'defaultdict 'perché all'interno del metodo' __missing__' si potrebbe aggiungere qualche logica per catturare un potenziale bug. Con 'defaultdict' mi fa sempre rabbrividire perché non otterrò un KeyError quando faccio un refuso. –

0

Due modi.

Uno è quello di assicurarsi che i dizionari siano standard, e quando li leggi hanno tutti i campi. L'altro è fare attenzione quando si accede ai dizionari.

Ecco un esempio di rendere sicuro il vostro dizionari sono standard:

__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 

Ecco un esempio di essere attenti quando si accede ai dizionari:

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