如何遍历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; }, []); }