【问题标题】:In javascript, test for property deeply nested in object graph?在javascript中,测试深深嵌套在对象图中的属性?
【发布时间】:2011-05-19 14:04:11
【问题描述】:

我从 CouchDB 数据库中收集了一组不同的、复杂的 JSON 对象。每个都包含许多级别的嵌套属性——例如,

tps_report.personnel_info.productivity.units_sold = 8  

我想遍历这些对象并用它们做一些事情:例如,

// writes units sold from each TPS report:
for (i in tpsReports) {
  if (tpsReports[i].personnel_info.productivity.units_sold < 10) {
    fireEmployee();
  }
}

问题在于许多 TPS 报告没有设置所有这些属性。因此,如果我尝试这个,当循环第一次到达没有“personnel_info”属性的报告时,我会得到一个错误,从而试图找到“未定义”的“生产力”属性。我宁愿发生的是条件只是跳过它并继续。

我看到了两种解决方法,这两种方法对我来说都很难看

  1. 使用嵌套条件分别测试每个属性
  2. 将该行包含在 try/catch 块中以捕获错误并忽略它

我更喜欢 PHP 的 isset() 函数,无论你提供什么,它都不会抛出错误——它只会告诉你你正在寻找的特定变量是否存在或不是。所以,像

// writes units sold from each TPS report:
for (i in tpsReports) {
  if (isset(tpsReports[i].personnel_info.productivity.units_sold)){
    if (tpsReports[i].personnel_info.productivity.units_sold < 10) {
      fireEmployee();
    }
  }
}

有什么想法吗?

【问题讨论】:

标签: javascript object graph properties


【解决方案1】:
function isset(obj, propStr) {
    var parts = propStr.split(".");
    var cur = obj;
    for (var i=0; i<parts.length; i++) {
        if (!cur[parts[i]])
            return false;
        cur = cur[parts[i]];
    }
    return true;
}

请注意,第二个参数是一个字符串,因此在访问不存在属性的属性时不会引发异常。

【讨论】:

    【解决方案2】:

    我真的很喜欢 jsonpath 的优雅,相当于 xpath,但是对于 json。

    http://goessner.net/articles/JsonPath/

    您可以在此处执行如下表达式:

    var units_sold = jsonPath(tpsResports, '$.[*].personnel_info.productivity.units_sold');
    // units_sold is array of found values... 
    

    (我没有仔细检查我的表达,你的例子中你想要的可能是错误的)

    【讨论】:

      【解决方案3】:

      丑陋的方式:

      for (i in tpsReports) {
        try {
          if(tpsReports[i].personnel_info.productivity.units_sold < 10) {
            fireEmployee();
          }
        } catch (e) {}
      }
      

      【讨论】:

      • 谢谢,这就是我在“2. 将行包含在 try/catch 块中以捕获错误并忽略它”中所指的方法
      【解决方案4】:

      定义了一个函数 on this blog 来安全地从 JS 对象中读取嵌套属性

      它允许你挖掘一个对象的属性......即。

      safeRead(tps_report, 'personnel_info', 'productivity', 'units_sold');
      

      如果对象链的任何部分为空或未定义,则返回一个空字符串......

      【讨论】:

        【解决方案5】:
        /**
         * units sold from each TPS report
         */
        
        var units;
        
        // the hard way
        units = (report && report.personnel && report.personnel.info &&
                report.personnel.info.sales && report.personnel.info.sales.units &&
                report.personnel.info.sales.units.sold) || 0;
        
        // the easy way
        units = selectn('personnel.info.sales.units.sold', report) || 0;
        
        // resulting action
        if (units < 10) fireEmployee();
        

        无耻插件:我是selectn的作者。可通过npm install selectnbower install selectncomponent install wilmoore/selectn 获得。

        查看自述文件中的示例,了解为什么这比 isset 克隆更好。您还可以将其用作filter 谓词,以便清除不包含特定深度嵌套属性的嵌套对象。

        【讨论】:

          【解决方案6】:

          您可以使用我的 ObjectPath 来查询大型嵌套 JSON 文档。正如问题中提到的那样,我正在构建它的原因是在编程语言中缺乏使用 JSON 的良好工具。

          该项目是开源的并在 AGPL 许可下。

          http://adriank.github.io/ObjectPath/

          Javascript 实现没有经过优化,并且缺少 Python 的一半功能,但如果社区需要,我很想添加新的东西——只要告诉我什么对你很重要。

          【讨论】:

            猜你喜欢
            • 2018-09-04
            • 2011-07-08
            • 1970-01-01
            • 2020-04-07
            • 2019-02-03
            • 1970-01-01
            • 1970-01-01
            • 2019-04-08
            • 2020-10-30
            相关资源
            最近更新 更多