Проверьте, существуют ли ключи/узлы JSON
Я использую API карт Google для извлечения информации о городе и состоянии/регионе из поиска почтового кода. Проблема в том, что в некоторых случаях поиск почтового кода не будет получать название города. Пример: 92625 (U.S).
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());
}
});
В некоторых случаях, как упоминалось выше, в результате не будет имени города, поэтому для города будет ошибка undefined, поскольку ключевая локация не существует. Эта ошибка предотвращает запуск остальной части script.
Я смог исправить это...
if (place.AddressDetails.Country.AdministrativeArea.SubAdministrativeArea.Locality != null)
var city = place.AddressDetails.Country.AdministrativeArea.SubAdministrativeArea.Locality.LocalityName;
else
var city = '';
... но у меня есть параноик по поводу аналогичной ошибки для других ключей. Например: если AdministrativeArea undefined, указанный выше оператор IF также вызывает ошибку undefined. Поэтому следует ли проверять, существует ли каждый ключ /Node? Кажется, это грязный подход, потому что некоторые из этих клавиш имеют глубину более 5 уровней... есть ли более простой способ сделать это, может быть, какой-то метод JQuery, с которым я не знаком?
Ответы
Ответ 1
В качестве альтернативы вы можете создать функцию, которая дает вам настройки по умолчанию:
function valueOrDefault(val, def) {
if (def == undefined) def = "";
return val == undefined ? def : val;
}
И затем используйте его следующим образом:
var place = response.Placemark[0];
var state = valueOrDefault(place.AddressDetails.Country.AdministrativeArea.AdministrativeAreaName);
var city = valueOrDefault(place.AddressDetails.Country.AdministrativeArea.SubAdministrativeArea.Locality.LocalityName);
Лично я считаю, что это немного лучше писать, чем предложение p00ya, хотя это немного взломано, играя в объектах undefined... можно было бы изменить его на это:
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
Ответ 2
Вы можете использовать функцию, которая "сверлит" вниз через все уровни вложенности, по умолчанию для пустой строки, если она не может зайти так далеко.
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"]));
Ответ 3
Мне нравится подход back2dos, но я думаю, что его можно было бы улучшить, чтобы не сбой с 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
Эта функция отлично подходит для проверки глубинных структур возврата JSON из служб AJAX, таких как freebase или YQL.
Ответ 4
Вы смотрите только на первый результат, который дает геокодер:
var place = response.Placemark[0];
getLocations() возвращает список нескольких результатов. Если первый не имеет этого, один из следующих результатов почти наверняка будет.