检查是否存在JSON密钥/节点

时间:2009-07-15 03:15:20

标签: javascript json google-maps

我正在使用Google Map API从邮政编码查找中检索城市+州/地区信息。问题是,在某些情况下,邮政编码查找不会检索城市名称。一个例子是92625(美国)。

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());
    }
});

在某些情况下,如上所述,结果中不会有城市名称,因此城市将存在未定义的错误,因为关键位置不存在。此错误会阻止脚本的其余部分运行。

我能够通过......来补救它。

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

...但是这让我对其他键的类似错误感到偏执。例如:如果未定义AdministrativeArea,则上述IF语句也会导致未定义的错误。那么我应该检查每个Key / Node是否存在?似乎是一个混乱的方法,因为其中一些键是5级以上的深度...是否有更容易的方法,可能是一些我不熟悉的JQuery方法?

4 个答案:

答案 0 :(得分:9)

或者,您可以创建一个函数,它为您提供默认值:

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的提议更好一点,虽然它在未定义的对象中有点笨拙地摆弄......但是可能会改变它:

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

答案 1 :(得分:3)

你可以使用一个在所有嵌套级别“向下钻取”的函数,如果它不能达到那么远,则默认为空字符串。

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"]));

答案 2 :(得分: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

这种函数非常适合从AJAX服务(如freebase或YQL)验证深层JSON返回结构。

答案 3 :(得分:0)

您只关注地理编码器为您提供的第一个结果:

var place = response.Placemark[0];

getLocations()返回多个结果的列表。如果第一个没有它,那么接下来几个结果中的一个几乎肯定会。