检查JSON键/节点是否存在

15

我正在使用Google地图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());
    }
});

如上所述,在某些情况下,结果中将没有城市名称,因此city变量报undefined错误,因为键“Locality”不存在。这个错误会阻止脚本的其余部分运行。

我通过...来解决这个问题。

    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个回答

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

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

3

我喜欢back2dos的方法,但我认为它可以改进,以避免出现ReferenceError:

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返回结构。


0

您只看到了地理编码器给出的第一个结果:

var place = response.Placemark[0];

getLocations()返回一个由多个结果组成的列表。 如果第一个没有它,则下几个结果中肯定有。


在上面的例子中,92625始终只有1个结果。 - Seth

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接