如何遍历JSON对象定位特定属性并将其内容推送到数组?

我正在使用一个JSON对象,它可以在任何叶子上有一个属性ids 。 我想遍历这个对象,find所有ids属性的实例,并将每个id存储在一个集合中。

嘲笑JSON对象( ids属性可能在更深的属性位置)。

 { "id": "b38a683d-3fb6-408f-9ef6-f4b853ed1193", "foo": { "ids": [ { "id": "bd0bf3bd-d6b9-4706-bfcb-9c867e47b881" }, { "id": "d1cc529d-d5d2-4460-b2bb-acf24a7c5999" }, { "id": "b68d0c8c-548e-472f-9b01-f25d4b199a71" } ], "baz": "super" }, "bar": { "ids": [ { "id": "bd0bf3bd-d6b9-4706-bfcb-9c867e47b881" }, { "id": "d1cc529d-d5d2-4460-b2bb-acf24a7c5999" }, { "id": "b68d0c8c-548e-472f-9b01-f25d4b199a71" } ] } } 

我正在使用下面的代码来遍历上面的JSON。

 var jsonFile = require('./file_test.json'); // the above in my local directory function traverse(obj, ids) { for (var prop in obj) { if (typeof obj[prop] == "object" && obj[prop]) { if (prop == 'ids') { for (var i = obj[prop].length - 1; i >= 0; i--) { ids.push(obj[prop][i]._id); }; } traverse(obj[prop], ids); } } } var ids = new Array(); traverse(jsonFile, ids); console.log('ids', ids); 

以上networking如下:

 ids [ 'b68d0c8c-548e-472f-9b01-f25d4b199a71', 'd1cc529d-d5d2-4460-b2bb-acf24a7c5999', 'bd0bf3bd-d6b9-4706-bfcb-9c867e47b881', 'b68d0c8c-548e-472f-9b01-f25d4b199a71', 'd1cc529d-d5d2-4460-b2bb-acf24a7c5999', 'bd0bf3bd-d6b9-4706-bfcb-9c867e47b881' ] 

虽然我的代码工作,我不相信我是这样做最有效率或最好的方式。 有没有更好的方式来查找ids属性的所有实例? 也许不通过一个数组,而是返回一个? 或者设置一个ids数组的callback?

你有什么好,但是这是一个短一点,使用.map函数:

 var jsonFile = require('./file_test.json'); // the above in my local directory function traverse(obj) { var ids = []; for (var prop in obj) { if (typeof obj[prop] == "object" && obj[prop]) { if (prop == 'ids') { ids = obj[prop].map(function(elem){ return elem.id; }) } ids =ids.concat(traverse(obj[prop])); } } return ids; } var ids =traverse(jsonFile); console.log('ids', ids); 

如果数据实际上是一个JSONstring,而不是一个JavaScript对象,你可能有这样的:

 // assuming `json` is the data string var ids = []; var data = JSON.parse(json, function(key, value) { if (key === "id") ids.push(value); return value; }); 

请参阅JSON.parse方法上的reviver

你基本上想要做的是对这个JSON对象进行树search,对吗? 所以如果我们假设ids总是一个叶子,那么我们不需要traverse这些节点,因为我们知道它们在叶子上,并且将包含我们想要的东西。

  • if {...} traverse 改为 if {...} else {traverse}

如果可以将ids的数据结构更改为string列表而不是对象列表,那么您将能够将迭代保存在数组上,并将其合并到传入的ids数组中,但完全取决于上下文以及是否可以进行此更改!

对不起,我没有更多的帮助!

假设ES5本地或通过垫片可用:

 function gimmeIds(obj) { return Object.keys(obj||{}) .reduce(function(ids, key) { if(key === 'ids') { return ids.concat(obj[key].map(function(idObj) { return idObj.id; })); } if(obj[key] && typeof obj[key] == 'object') { return ids.concat(gimmeIds(obj[key])); } return ids; }, []); }