2009-04-06 4 views

Trả lời

47

Một JSON đối tượng chỉ đơn giản là một đối tượng Javascript Đó là thực tế những gì JSON là viết tắt của:.. JavaScript Object Notation Vì vậy, bạn muốn đi qua một đối tượng JSON tuy nhiên bạn muốn chọn để "đi qua" một đối tượng javascript nói chung.

trong jQuery, tôi muốn làm một cái gì đó giống như

$.each(myJsonObj, function(key,val){ 
    // do something with key and val 
}); 

bạn luôn có thể viết một hàm đệ quy xuống vực đối tượng:

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

Đây phải là điểm khởi đầu tốt. Tôi khuyên bạn nên sử dụng jQuery cho những thứ như vậy, vì các tiện ích của chúng như mỗi vòng lặp làm cho việc viết mã như vậy dễ dàng hơn nhiều.

+3

Tránh traverse (v) trong đó v == null, vì (typeof rỗng == "đối tượng") === đúng. 'chức năng đi ngang (jsonObj) { nếu (jsonObj && typeof jsonObj ==" đối tượng ") { ...' –

191

Nếu bạn nghĩ rằng jQuery là loại overkill cho một nhiệm vụ nguyên thủy như vậy, bạn có thể làm một cái gì đó như thế:

//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); 
+3

có thể tôi bị mù nhưng có vẻ như chức năng truyền tải thiếu dấu ngoặc kép '}'? – cambo

+0

cũng thiếu từ khóa var trong vòng lặp – rochal

+0

@rochal: Tôi không thể yêu cầu 'var' này nhưng phải được xem là kiểu mã hóa tốt. – TheHippo

10

Phụ thuộc vào những gì bạn muốn làm. Dưới đây là một ví dụ về đi qua một cây đối tượng JavaScript, phím in ấn và giá trị như nó đi:

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 
26

Có một thư viện mới để vượt qua dữ liệu JSON với JavaScript hỗ trợ nhiều trường hợp sử dụng khác nhau.

https://npmjs.org/package/traverse

https://github.com/substack/js-traverse

Nó hoạt động với tất cả các loại đối tượng JavaScript. Nó thậm chí phát hiện chu kỳ.

Nó cũng cung cấp đường dẫn của mỗi nút.

+1

js-traverse dường như cũng có sẵn qua npm trong node.js. – Ville

+0

Có. Nó chỉ được gọi là đi qua đó. Và họ có một trang web đáng yêu! Cập nhật câu trả lời của tôi để bao gồm nó. –

+0

Cảm ơn bạn đã trỏ đến js-traverse. Tuy nhiên, nói đúng, liên kết không thay thế câu trả lời thích hợp, tức là một liên kết có mẫu mã. –

28
function traverse(o) { 
    for (i in o) { 
     if (!!o[i] && typeof(o[i])=="object") { 
      console.log(i, o[i]) 
      traverse(o[i]); 
     } 
    } 
} 
+5

Bạn có thể giải thích lý do tại sao nó tốt hơn? – Dementic

+3

Nếu phương pháp có nghĩa là để làm bất cứ điều gì khác hơn là đăng nhập bạn nên kiểm tra null, null vẫn là một đối tượng. – wi1

+2

@ wi1 Đồng ý với bạn, có thể kiểm tra '!! o [i] && typeof o [i] == 'đối tượng'' – pilau

-1

Giải pháp tốt nhất đối với tôi là như sau:

đơn giản và không cần dùng bất kỳ khuôn khổ

var doSomethingForAll = function (arg) { 
     if (arg != undefined && arg.length > 0) { 
      arg.map(function (item) { 
        // do something for item 
        doSomethingForAll (item.subitem) 
      }); 
     } 
    } 
+0

tại sao lại giảm hạng? ai đó có thể giải thích nó? – Asqan

-1

Bạn có thể nhận được tất cả các phím/giá trị và duy trì hệ thống phân cấp với

này
// 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') 

Đây là một sửa đổi trên (https://stackoverflow.com/a/25063574/1484447)

4

Tôi muốn sử dụng giải pháp hoàn hảo của @TheHippo trong một chức năng ẩn danh, mà không cần sử dụng các chức năng xử lý và kích hoạt. Sau đây đã làm việc cho tôi, chia sẻ cho các lập trình viên mới làm quen như bản thân mình.

(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); 
+0

Cảm ơn vì điều này! – Mike

7

Nếu bạn đang đi qua một thực tế JSON chuỗi sau đó bạn có thể sử dụng một hàm 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) 
}) 

Khi đi qua một đối tượng:

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) 
}) 
-1
   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>); 
       } 
2

Hầu hết javascript động cơ không tối ưu hóa đệ quy đuôi (điều này có thể không phải là một vấn đề nếu JSON của bạn không sâu lồng nhau), nhưng tôi thường sai về mặt thận trọng và thay vào đó lặp lại, ví dụ

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) 
-1

Tôi đã tạo thư viện để duyệt và chỉnh sửa các đối tượng JS lồng nhau sâu. Kiểm tra API ở đây: https://github.com/dominik791

Bạn cũng có thể chơi với thư viện tương tác sử dụng ứng dụng bản demo: https://dominik791.github.io/obj-traverse-demo/

Ví dụ về sử dụng: Bạn nên luôn luôn có đối tượng gốc mà là tham số đầu tiên của mỗi phương pháp:

var rootObj = { 
    name: 'rootObject', 
    children: [ 
    { 
     'name': 'child1', 
     children: [ ... ] 
    }, 
    { 
     'name': 'child2', 
     children: [ ... ] 
    } 
    ] 
}; 

Tham số thứ hai luôn là tên của thuộc tính chứa đối tượng lồng nhau. Trong trường hợp trên, nó sẽ là 'children'.

Tham số thứ ba là một đối tượng mà bạn sử dụng để tìm đối tượng/đối tượng mà bạn muốn tìm/sửa đổi/xóa. Ví dụ: nếu bạn đang tìm đối tượng có id bằng 1, thì bạn sẽ vượt qua { id: 1} làm tham số thứ ba.

Và bạn có thể:

  1. findFirst(rootObj, 'children', { id: 1 }) để tìm thấy đầu tiên đối tượng với id === 1
  2. findAll(rootObj, 'children', { id: 1 }) để tìm tất cả đối tượng với id === 1
  3. findAndDeleteFirst(rootObj, 'children', { id: 1 }) để xóa đối tượng phù hợp đầu tiên
  4. findAndDeleteAll(rootObj, 'children', { id: 1 }) để xóa tất cả phù hợp đối tượng

replacementObj được sử dụng như là tham số cuối cùng trong hai phương pháp cuối cùng:

  1. findAndModifyFirst(rootObj, 'children', { id: 1 }, { id: 2, name: 'newObj'}) thay đổi đối tượng đầu tiên tìm thấy với id === 1 đến { id: 2, name: 'newObj'}
  2. findAndModifyAll(rootObj, 'children', { id: 1 }, { id: 2, name: 'newObj'}) thay đổi tất cả các đối tượng với id === 1 đến { id: 2, name: 'newObj'}
0

Tập lệnh của tôi:

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

Input JSON:

[ 
    { 
     "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": [] 
        } 
       ] 
      } 
     ] 
    } 
] 

Chức năng Call:

callback_func(inp_json); 

Output theo Cần tôi:

["output/f1/ver"] 
1

Đối với một cách mới để làm điều đó nếu bạn không nhớ thả IE và chủ yếu hỗ trợ nhiều trình duyệt hiện tại hơn (kiểm tra kangax's es6 table để tương thích). Bạn có thể sử dụng es2015 generators cho việc này. Tôi đã cập nhật câu trả lời của @ TheHippo cho phù hợp. Tất nhiên nếu bạn thực sự muốn hỗ trợ IE, bạn có thể sử dụng trình biên dịch JavaScript babel.

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

Nếu bạn muốn chỉ sở hữu tính đếm được (các thuộc tính chuỗi cơ bản phi nguyên mẫu), bạn có thể thay đổi nó để lặp sử dụng Object.keysfor...of vòng lặp thay vì:

//your object 
 
var o = { 
 
    foo:"bar", 
 
    arr:[1,2,3], 
 
    subo: { 
 
     foo2:"bar2" 
 
    } 
 
}; 
 

 
function* traverse(o,func) { 
 
    for (var i of Object.keys(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); 
 
}

0

var test = { 
 
    depth00: { 
 
     depth10: 'string' 
 
     , depth11: 11 
 
     , depth12: { 
 
      depth20:'string' 
 
      , depth21:21 
 
     } 
 
     , depth13: [ 
 
      { 
 
       depth22:'2201' 
 
       , depth23:'2301' 
 
      } 
 
      , { 
 
       depth22:'2202' 
 
       , depth23:'2302' 
 
      } 
 
     ] 
 
    } 
 
    ,depth01: { 
 
     depth10: 'string' 
 
     , depth11: 11 
 
     , depth12: { 
 
      depth20:'string' 
 
      , depth21:21 
 
     } 
 
     , depth13: [ 
 
      { 
 
       depth22:'2201' 
 
       , depth23:'2301' 
 
      } 
 
      , { 
 
       depth22:'2202' 
 
       , depth23:'2302' 
 
      } 
 
     ] 
 
    } 
 
    , depth02: 'string' 
 
    , dpeth03: 3 
 
}; 
 

 

 
function traverse(result, obj, preKey) { 
 
    if(!obj) return []; 
 
    if (typeof obj == 'object') { 
 
     for(var key in obj) { 
 
      traverse(result, obj[key], (preKey || '') + (preKey ? '[' + key + ']' : key)) 
 
     } 
 
    } else { 
 
     result.push({ 
 
      key: (preKey || '') 
 
      , val: obj 
 
     }); 
 
    } 
 
    return result; 
 
} 
 

 
document.getElementById('textarea').value = JSON.stringify(traverse([], test), null, 2);
<textarea style="width:100%;height:600px;" id="textarea"></textarea>

+0

đã gửi hồ sơ để gửi mẫu đơn đăng ký/json – seung