【问题标题】:Check if JSON keys/nodes exist检查 JSON 键/节点是否存在
【发布时间】:2009-07-15 03:15:19
【问题描述】:

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

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

我可以通过...解决它

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

...但这让我对其他键的类似错误感到偏执。例如:如果 AdministrativeArea 未定义,上述 IF 语句也会导致未定义错误。那么我应该检查每个键/节点是否存在吗?似乎是一种混乱的方法,因为其中一些键的深度超过 5 级......有没有更简单的方法来解决它,也许是我不熟悉的一些 JQuery 方法?

【问题讨论】:

    标签: javascript json google-maps


    【解决方案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 的建议写得好一些,虽然在未定义的对象中摆弄有点笨拙......也许可以将其更改为:

    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 的方法,但我认为它可以改进,以免因ReferenceErrors 而失败:

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

        【讨论】:

          【解决方案4】:

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

          var place = response.Placemark[0];
          

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

          【讨论】:

          • 在上面的例子中,92625总是只有1个结果。
          猜你喜欢
          • 1970-01-01
          • 2017-06-03
          • 2021-08-16
          • 1970-01-01
          • 1970-01-01
          • 2011-08-31
          • 1970-01-01
          • 2021-06-27
          • 1970-01-01
          相关资源
          最近更新 更多