在javascript中,测试对象图中深层嵌套的属性?

发布于 2024-10-05 18:50:11 字数 965 浏览 3 评论 0原文

我从 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”属性的报告时,我会收到错误,从而尝试找到“undefined”的“生产力”属性。我宁愿发生的是条件只是跳过它并继续。

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

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

什么想法吗?

I've got a collection of disparate, complex JSON objects from a CouchDB database. Each contains many levels of nested properties--for example,

tps_report.personnel_info.productivity.units_sold = 8  

I want to iterate through these objects and do stuff with them: for instance,

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

The problem is that many TPS reports don't have all these properties set. So if I try this, I'll get an error the first time the loop gets to a report without the "personnel_info" property and thus tries to find the "productivity" property of "undefined." What I'd rather happen is that the conditional just skips it and continues.

I see two ways around this, both of which seem ugly to me

  1. test for each property separately with nested conditionals
  2. enclose the line in a try/catch block to catch the error and ignore it

What I'd prefer would be something like PHP's isset() function, which won't throw an error regardless of what you feed it--it'll just tell you whether the particular variable you're looking for exists or not. So, like

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

Any thoughts?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

此岸叶落 2024-10-12 18:50:11
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;
}

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

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

Note that the second parameter is a string, so the exception doesn't get thrown when accessing a property on a nonexistent property.

治碍 2024-10-12 18:50:11

在此博客上定义了一个函数来安全地从 JS 对象读取嵌套属性

它允许您挖掘对象的属性...即。

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

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

Theres a function defined on this blog to safely read nested properties from a JS object

It allows you to mine an object for properties... ie.

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

and if any part of the object chain is null or undefined it returns an empty string....

故事未完 2024-10-12 18:50:11
/**
 * 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 克隆更好。您还可以将其用作 过滤器 谓词,以便您可以清除不包含的嵌套对象包含特定的深层嵌套属性。

/**
 * 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();

Shameless plug: I am the author of selectn. It is avaialble via npm install selectn or bower install selectn or component install wilmoore/selectn.

Check out the examples on the readme to find out why this is better than an isset clone. You can also use it as a filter predicate so you can scrub out nested objects that do not contain a particular deeply nested property.

眼眸印温柔 2024-10-12 18:50:11

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

该项目是开源的,并获得 AGPL 许可。

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

Javascript 实现未优化,缺少一半Python 的功能,但如果社区需要的话,我热衷于添加新的东西 - 只需告诉我什么对你来说是至关重要的。

You can use my ObjectPath to query big nested JSON documents. The cause I'm building it is the lack of good tools in programming languages to work with JSON just as mentioned in the question.

The project is open sourced and under AGPL license.

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

Javascript implementation is not optimized and lacks half of the Python's functionality but I'm keen to add new things if needed by community - just ping me about what is crucial to you.

時窥 2024-10-12 18:50:11

我真的很喜欢 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... 

我没有仔细检查我的表达,它可能与您在示例中想要的内容不同)

I really like the elegance of jsonpath, an equivalent to xpath, but for json.

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

There you can do an expression like:

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

(I didn't double check my expression, it may be wrong for what you want in your example)

夏花。依旧 2024-10-12 18:50:11

丑陋的方式:

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

The ugly way :

for (i in tpsReports) {
  try {
    if(tpsReports[i].personnel_info.productivity.units_sold < 10) {
      fireEmployee();
    }
  } catch (e) {}
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文