使用JavaScript遍历JSON对象树的所有节点
我想遍历一个JSON对象树,但找不到任何库。 这似乎并不困难,但感觉像重新发明轮子。
在XML中有这么多教程展示了如何遍历一个DOM树:(
如果你认为jQuery对于这样一个原始的任务是一种矫枉过正 ,你可以这样做:
//your object var o = { foo:"bar", arr:[1,2,3], subo: { foo2:"bar2" } }; //called with every property and its value function process(key,value) { console.log(key + " : "+value); } function traverse(o,func) { for (var i in o) { func.apply(this,[i,o[i]]); if (o[i] !== null && typeof(o[i])=="object") { //going one step down in the object tree!! traverse(o[i],func); } } } //that's all... no magic, no bloated framework traverse(o,process);
JSON对象只是一个Javascript对象。 这实际上是JSON代表的:JavaScript Object Notation。 所以你会遍历一个JSON对象,但是你会select“遍历”一个Javascript对象。
在jQuery中,我会做类似的事情
$.each(myJsonObj, function(key,val){ // do something with key and val });
你总是可以编写一个recursion下降到对象的函数:
function traverse(jsonObj) { if( typeof jsonObj == "object" ) { $.each(jsonObj, function(k,v) { // k is either an array index or object key traverse(v); }); } else { // jsonOb is a number or string } }
这应该是一个很好的起点。 我强烈build议使用jQuery来做这样的事情,因为他们的工具比如每个循环都会使得编写这样的代码变得更容易。
function traverse(o ) { for (i in o) { if (!!o[i] && typeof(o[i])=="object") { console.log(i, o[i]) traverse(o[i] ); } } }
这个更好,更容易实现。
有一个新的用于遍历JavaScript的JSON数据库,支持许多不同的用例。
https://npmjs.org/package/traverse
https://github.com/substack/js-traverse
它适用于各种JavaScript对象。 它甚至检测周期。
它也提供了每个节点的path。
取决于你想做什么。 以下是一个遍历JavaScript对象树的例子,它可以像下面这样打印键和值:
function js_traverse(o) { var type = typeof o if (type == "object") { for (var key in o) { print("key: ", key) js_traverse(o[key]) } } else { print(o) } } js> foobar = {foo: "bar", baz: "quux", zot: [1, 2, 3, {some: "hash"}]} [object Object] js> js_traverse(foobar) key: foo bar key: baz quux key: zot key: 0 1 key: 1 2 key: 2 3 key: 3 key: some hash
如果你遍历一个实际的JSON string,那么你可以使用reviver函数。
function traverse (json, callback) { JSON.parse(json, function (key, value) { if (key !== '') { callback.call(this, key, value) } return value }) } traverse('{"a":{"b":{"c":{"d":1}},"e":{"f":2}}}', function (key, value) { console.log(arguments) })
遍历对象时:
function traverse (obj, callback, trail) { trail = trail || [] Object.keys(obj).forEach(function (key) { var value = obj[key] if (Object.getPrototypeOf(value) === Object.prototype) { traverse(value, callback, trail.concat(key)) } else { callback.call(obj, key, value, trail) } }) } traverse({a: {b: {c: {d: 1}}, e: {f: 2}}}, function (key, value, trail) { console.log(arguments) })
我想在匿名函数中使用@TheHippo的完美解决scheme,而不使用进程和触发器function。 以下为我工作,分享像我这样的新手程序员。
(function traverse(o) { for (var i in o) { console.log('key : ' + i + ', value: ' + o[i]); if (o[i] !== null && typeof(o[i])=="object") { //going on step down in the object tree!! traverse(o[i]); } } }) (json);
大多数Javascript引擎不优化尾recursion(如果你的JSON没有深度嵌套,这可能不是问题),但是我通常会在谨慎的方面犯错,而不是做迭代。
function traverse(o, fn) { const stack = [o] while (stack.length) { const obj = stack.shift() Object.keys(obj).forEach((key) => { fn(key, obj[key], obj) if (obj[key] instanceof Object) { stack.unshift(obj[key]) return } }) } } const o = { name: 'Max', legal: false, other: { name: 'Maxwell', nested: { legal: true } } } const fx = (key, value, obj) => console.log(key, value) traverse(o, fx)
我的脚本:
op_needed = []; callback_func = function(val) { var i, j, len; results = []; for (j = 0, len = val.length; j < len; j++) { i = val[j]; if (i['children'].length !== 0) { call_func(i['children']); } else { op_needed.push(i['rel_path']); } } return op_needed; };
inputJSON:
[ { "id": null, "name": "output", "asset_type_assoc": [], "rel_path": "output", "children": [ { "id": null, "name": "output", "asset_type_assoc": [], "rel_path": "output/f1", "children": [ { "id": null, "name": "v#", "asset_type_assoc": [], "rel_path": "output/f1/ver", "children": [] } ] } ] } ]
函数调用:
callback_func(inp_json);
根据我的需要输出:
["output/f1/ver"]
如果您不介意放弃IE并主要支持更多的浏览器(请检查kangax的es6表以获得兼容性),请使用更新的方法 。 你可以使用es2015 发电机 。 我已经更新了TheHippo的回答。 当然,如果你真的想要IE支持,你可以使用babel JavaScript转换器。
//your object var o = { foo:"bar", arr:[1,2,3], subo: { foo2:"bar2" } }; function* traverse(o,func) { for (var i in o) { yield [i,o[i]]; if (o[i] !== null && typeof(o[i])=="object") { //going one step down in the object tree!! yield* traverse(o[i],func); } } } //that's all... no magic, no bloated framework for(var [key, value] of traverse(o)) { console.log(key, value); }
对我来说最好的解决办法是:
简单而不使用任何框架
var doSomethingForAll = function (arg) { if (arg != undefined && arg.length > 0) { arg.map(function (item) { // do something for item doSomethingForAll (item.subitem) }); } }
你可以得到所有的键/值,并保持这个层次
// get keys of an object or array function getkeys(z){ var out=[]; for(var i in z){out.push(i)}; return out; } // print all inside an object function allInternalObjs(data, name) { name = name || 'data'; return getkeys(data).reduce(function(olist, k){ var v = data[k]; if(typeof v === 'object') { olist.push.apply(olist, allInternalObjs(v, name + '.' + k)); } else { olist.push(name + '.' + k + ' = ' + v); } return olist; }, []); } // run with this allInternalObjs({'a':[{'b':'c'},{'d':{'e':5}}],'f':{'g':'h'}}, 'ob')
var localdata = [{''}]// Your json array for (var j = 0; j < localdata.length; j++) {$(localdata).each(function(index,item) { $('#tbl').append('<tr><td>' + item.FirstName +'</td></tr>); }
我创build了库来遍历和编辑深层嵌套的JS对象。 在这里查看API: https : //github.com/dominik791
您还可以使用演示应用程序交互式使用图书馆: https : //dominik791.github.io/obj-traverse-demo/
用法示例:您应始终拥有每个方法的第一个参数:
var rootObj = { name: 'rootObject', children: [ { 'name': 'child1', children: [ ... ] }, { 'name': 'child2', children: [ ... ] } ] };
第二个参数总是保存嵌套对象的属性的名称。 在上述情况下,这将是'children'
。
第三个参数是用于查找要查找/修改/删除的对象/对象的对象。 例如,如果您正在查找id等于1的对象,那么您将传递{ id: 1}
作为第三个参数。
你可以:
-
findFirst(rootObj, 'children', { id: 1 })
查找id === 1
第一个对象 -
findAll(rootObj, 'children', { id: 1 })
查找id === 1
所有对象 -
findAndDeleteFirst(rootObj, 'children', { id: 1 })
删除第一个匹配的对象 -
findAndDeleteAll(rootObj, 'children', { id: 1 })
删除所有匹配的对象
replacementObj
被用作最后两个方法中的最后一个参数:
-
findAndModifyFirst(rootObj, 'children', { id: 1 }, { id: 2, name: 'newObj'})
将id === 1
第一个find的对象改为{ id: 2, name: 'newObj'}
-
findAndModifyAll(rootObj, 'children', { id: 1 }, { id: 2, name: 'newObj'})
将id === 1
findAndModifyAll(rootObj, 'children', { id: 1 }, { id: 2, name: 'newObj'})
id === 1
所有对象改为{ id: 2, name: 'newObj'}