In javascript, testare la proprietà profondamente annidata nel grafo degli oggetti?

Ho una collezione di oggetti JSON complessi e disparati da un database CouchDB. Ciascuno contiene molti livelli di proprietà annidate, ad esempio

tps_report.personnel_info.productivity.units_sold = 8 

Voglio scorrere questi oggetti e fare cose con loro: ad esempio,

 // writes units sold from each TPS report: for (i in tpsReports) { if (tpsReports[i].personnel_info.productivity.units_sold < 10) { fireEmployee(); } } 

Il problema è che molti rapporti TPS non hanno tutte queste proprietà impostate. Quindi, se provo questo, ricevo un errore la prima volta che il ciclo arriva a un report senza la proprietà “personnel_info” e quindi cerca di trovare la proprietà “produttività” di “indefinito”. Quello che preferirei succedere è che il condizionale lo salta e continua.

Vedo due modi per aggirare questo, entrambi sembrano brutti per me

  1. prova per ogni proprietà separatamente con condizionali nidificati
  2. racchiudere la linea in un blocco try / catch per rilevare l’errore e ignorarlo

Quello che preferirei sarebbe qualcosa come la funzione isset () di PHP, che non genererà un errore a prescindere da cosa gli dai da mangiare – ti dirà solo se la particolare variabile che stai cercando esiste o meno. Quindi, come

 // writes units sold from each TPS report: for (i in tpsReports) { if (isset(tpsReports[i].personnel_info.productivity.units_sold)){ if (tpsReports[i].personnel_info.productivity.units_sold < 10) { fireEmployee(); } } } 

qualche idea?

 function isset(obj, propStr) { var parts = propStr.split("."); var cur = obj; for (var i=0; i 

Si noti che il secondo parametro è una stringa, quindi l'eccezione non viene generata quando si accede a una proprietà su una proprietà inesistente.

C’è una funzione definita in questo blog per leggere in sicurezza le proprietà nidificate da un object JS

Ti permette di estrarre un object per proprietà … cioè.

 safeRead(tps_report, 'personnel_info', 'productivity', 'units_sold'); 

e se una qualsiasi parte della catena di oggetti è nullo o indefinito restituisce una stringa vuota ….

 /** * units sold from each TPS report */ var units; // the hard way units = (report && report.personnel && report.personnel.info && report.personnel.info.sales && report.personnel.info.sales.units && report.personnel.info.sales.units.sold) || 0; // the easy way units = selectn('personnel.info.sales.units.sold', report) || 0; // resulting action if (units < 10) fireEmployee(); 

Spina senza vergogna: sono l'autore di selectn . È disponibile tramite npm install selectn o bower install selectn o component install wilmoore/selectn .

Guarda gli esempi sul readme per scoprire perché è meglio di un clone di isset . Puoi anche usarlo come predicato di filtro in modo da poter eliminare oggetti nidificati che non contengono una particolare proprietà profondamente annidata.

È ansible utilizzare il mio ObjectPath per interrogare documenti JSON di grandi dimensioni. La causa che sto costruendo è la mancanza di buoni strumenti nei linguaggi di programmazione per lavorare con JSON come menzionato nella domanda.

Il progetto è open source e sotto licenza AGPL.

http://adriank.github.io/ObjectPath/

L’implementazione di Javascript non è ottimizzata e manca la metà delle funzionalità di Python, ma sono ansioso di aggiungere nuove cose, se necessario, dalla comunità: basta fare un ping su ciò che è cruciale per te.

Mi piace molto l’eleganza di jsonpath, un equivalente di xpath, ma per json.

http://goessner.net/articles/JsonPath/

Qui puoi fare un’espressione come:

 var units_sold = jsonPath(tpsResports, '$.[*].personnel_info.productivity.units_sold'); // units_sold is array of found values... 

(Non ho ricontrollato la mia espressione, potrebbe essere sbagliato per quello che vuoi nel tuo esempio)

Il modo brutto:

 for (i in tpsReports) { try { if(tpsReports[i].personnel_info.productivity.units_sold < 10) { fireEmployee(); } } catch (e) {} }