2009-07-15 12 views
15

Używam interfejsu API Google Map do pobierania informacji o mieście i stanie/regionie z kodu pocztowego. Problem polega na tym, że w niektórych przypadkach wyszukiwanie kodu pocztowego nie spowoduje wyszukania nazwy miasta. Przykładem jest 92625 (U.S).Sprawdź, czy istnieją klucze/węzły JSON.

var g = new GClientGeocoder(); 
g.setBaseCountryCode('US'); 
g.getLocations('92625', function(response){ 
    if (response) { 
     var place = response.Placemark[0]; 
     var state = place.AddressDetails.Country.AdministrativeArea.AdministrativeAreaName; 
     var city = place.AddressDetails.Country.AdministrativeArea.SubAdministrativeArea.Locality.LocalityName; 
     GLog.write("City = "+city+" : State/Region = "+state+" : Country = " + g.getBaseCountryCode()); 
    } 
}); 

W niektórych przypadkach, jak wspomniano powyżej, nie będzie nazwę miasta w rezultacie więc nie będzie niezdefiniowany błąd dla miasta, ponieważ klucz Miejscowość nie istnieje. Ten błąd uniemożliwia działanie pozostałej części skryptu.

udało mi się go naprawić ...

if (place.AddressDetails.Country.AdministrativeArea.SubAdministrativeArea.Locality != null) 
     var city = place.AddressDetails.Country.AdministrativeArea.SubAdministrativeArea.Locality.LocalityName; 
    else 
     var city = ''; 

... ale to ma mnie paranoikiem o błędzie podobny do innych klawiszy. Np .: jeśli pole AdministrativeArea jest niezdefiniowane, powyższa instrukcja IF spowoduje również niezdefiniowany błąd. Czy powinienem sprawdzać, czy każdy klucz/węzeł istnieje? Wydaje się być niechlujnym podejściem, ponieważ niektóre z tych kluczy mają 5 poziomów głębokości ... czy jest łatwiejszy sposób na zrobienie tego, może jakaś metoda JQuery, której nie znam?

Odpowiedz

9

Alternatywnie, można utworzyć funkcję, która daje Domyślne:

function valueOrDefault(val, def) { 
    if (def == undefined) def = ""; 
    return val == undefined ? def : val; 
} 

a następnie używać go w ten sposób:

var place = response.Placemark[0]; 
var state = valueOrDefault(place.AddressDetails.Country.AdministrativeArea.AdministrativeAreaName); 
var city = valueOrDefault(place.AddressDetails.Country.AdministrativeArea.SubAdministrativeArea.Locality.LocalityName); 

Osobiście uważam, że to trochę ładniejszy piszę, niż propozycja p00ya, choć jest to trochę bezsensowne błądzenie w nieokreślonych obiektach ... można by to zmienić:

function drill(p, a) { 
a = a.split(".");//add this 
for (i in a) { 
    var key = a[i]; 
    if (p[key] == null) 
    return ''; 
    p = p[key]; 
} 
return p; 
} 
var obj = {foo:{bar:{baz:"quux"}}}; 
var s = drill(obj, "foo.bar.baz"));//and you can use a simple property chain 
3

Możesz użyć funkcji, która "wierci" w dół przez wszystkie poziomy zagnieżdżania, domyślnie do pustego ciągu, jeśli nie może dojść tak daleko.

function drill(p, a) { 
for (i in a) { 
    var key = a[i]; 
    if (p[key] == null) 
    return ''; 
    p = p[key]; 
} 
return p; 
} 
var obj = {foo:{bar:{baz:"quux"}}}; 
var s = drill(obj, ["foo", "bar", "baz"])); 
0

Widzisz tylko pierwszy rezultacie geocoder daje:

var place = response.Placemark[0]; 

getLocations() zwraca listę kilku wyników. Jeśli pierwszy tego nie ma, jeden z kolejnych wyników prawie na pewno będzie.

+0

W powyższym przykładzie zawsze jest tylko jeden wynik dla 92625. – Seth

3

Lubię podejście back2dos', ale myślę, że to może być ulepszona tak, aby nie zawieść z ReferenceError s:

function jPath(obj, a) { 
    a = a.split("."); 
    var p = obj||{}; 
    for (var i in a) { 
     if (p === null || typeof p[a[i]] === 'undefined') return null; 
     p = p[a[i]]; 
    } 
    return p; 
} 

// Tests 
var a = {b:{c:'Hello World!'}, c:null}; 

console.log(jPath(a, 'b.c')); // Hello World 
console.log(jPath(a, 'b.d')); // null 
console.log(jPath(a, 'e.f.g')); // null 
console.log(jPath(a, 'c'));  // null 

var z; 
console.log(jPath(z, 'c'));  // null 

Ten rodzaj funkcji jest wielki walidacji struktur głęboko powrotne JSON z usług AJAX takich jak wolnej zasady lub YQL.