2010-12-03 69 views
4

我从CouchDB数据库收集了一些不同的,复杂的JSON对象。每个包含嵌套属性的多层次 - 例如,在javascript中,测试属性深深嵌套在对象图中?

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”的“productivity”属性。我宁愿发生的是,条件只是跳过它并继续。

我看到周围这两种方式,这两种看似丑陋的我

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

有什么想法?

回答

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

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

0

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

(我没有仔细检查我的表达,也可能是错误的,你想在你的例子是什么)

0

丑陋的方式:

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

谢谢,这是我在“2.将该行放在try/catch块中以捕获错误并忽略它”的方法。 – thisismyname 2010-12-06 05:14:35

2

Theres a function defined on this blog安全地从JS对象读取嵌套的属性

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

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

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

2
/** 
* 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好。您还可以将它用作谓词谓词,以便擦除不包含特定深层嵌套属性的嵌套对象。

1

您可以使用我的ObjectPath查询大型嵌套JSON文档。我构建它的原因是编程语言中没有好的工具来处理JSON,就像问题中提到的一样。

该项目是开源和AGPL许可证。

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

Javascript实现不是最优化的,缺乏的Python的功能一半,但我渴望在需要时由社区增加新的东西 - 只要ping通我有什么事对你是重要的。