2017-07-19 75 views
0

我一直堅持我認爲是JS中的一個簡單問題。我想要做的是我有一個未知的深度JSON,如下所示:在JavaScript中遞歸地解析JSON樹

"A": { 
     "B": { 
      "e": "", 
      "f": { 
       "g": "", 
       "h": "" 
      }, 
      "C": { 
       "i": "", 
       "j": "", 
       "k": "", 
       "l": "" 
      }, 
      "D": { 
       "m": "", 
       "n": "", 
       "o": "", 
       "p": "" 
      }... 

json可以是任何深度的級別。我正在努力實現的是創建列祖列宗+本身各部分,使得爲「P」這將是["A", "B", "D", "p"]

我試着用遞歸像這樣:

build(json, '', []); 


function build(json, path, assets){ 
for (var elem in json) { 
    if(json.hasOwnProperty(elem)){ 
    if(json[elem] == 0){ 
     assets.push(elem); 

      //do stuff with the array 


     assets.pop(); 

     } else { 
     var parent = path + '/' + elem; 
     assets.push(parent); 
     build(json[elem], parent, assets); 
     return; 
     } 
    } 
    } 
    } 

這是一個簡化版本的功能,部分不能正常工作。我背後的想法是通過每個元素,如果它沒有孩子,我追加當前元素並使用它(我不需要保留數組,只是爲了這個用途),如果它有孩子,我追加當前元素並遞歸調用當前元素的方法。

解決方案的工作,直到達到第二個層次,所以「E」,「F」,「C」,「d」,它產生正確的,但在此之前將自己的孩子停止。

我錯過了什麼?

+0

嘗試刪除從代碼中返回的另一種方式,你可以做到這一點。 – Etherealm

回答

0

我不能完全遵循你的代碼,所以我只是從頭開始寫一個解決方案。

值得注意的是,我不知道是什麼== 0檢查是在你的代碼做(也許同樣的事情,我typeof(...) !== 'object'?),我不明白是什麼assetspath的意思做。

var obj = { 
 
    "A": { 
 
    "B": { 
 
     "e": "", 
 
     "f": { 
 
     "g": "", 
 
     "h": "" 
 
     }, 
 
     "C": { 
 
     "i": "", 
 
     "j": "", 
 
     "k": "", 
 
     "l": "" 
 
     }, 
 
     "D": { 
 
     "m": "", 
 
     "n": "", 
 
     "o": "", 
 
     "p": "" 
 
     }, 
 
    } 
 
    } 
 
}; 
 

 
function getPaths(obj, sofar) { 
 
    if (sofar === undefined) { 
 
    sofar = []; 
 
    } 
 

 
    // Leaf node, just return the path 
 
    if (typeof(obj) !== 'object') { 
 
    return [sofar]; 
 
    } 
 

 
    // Interior node 
 
    var paths = []; 
 
    Object.keys(obj).forEach(function (k) { 
 
    // For each child, recurse and concat 
 
    paths = paths.concat(getPaths(obj[k], sofar.concat([k]))); 
 
    }); 
 

 
    return paths; 
 
} 
 

 
console.log(getPaths(obj)); 
 

 
// Output: 
 
// [ [ 'A', 'B', 'e' ], 
 
// [ 'A', 'B', 'f', 'g' ], 
 
// [ 'A', 'B', 'f', 'h' ], 
 
// [ 'A', 'B', 'C', 'i' ], 
 
// [ 'A', 'B', 'C', 'j' ], 
 
// [ 'A', 'B', 'C', 'k' ], 
 
// [ 'A', 'B', 'C', 'l' ], 
 
// [ 'A', 'B', 'D', 'm' ], 
 
// [ 'A', 'B', 'D', 'n' ], 
 
// [ 'A', 'B', 'D', 'o' ], 
 
// [ 'A', 'B', 'D', 'p' ] ]

0

你可以使用一個陣列的訪問節點,並把它作爲結果的一部分。

function getPath(object, path) { 
 
    path = path || []; 
 
    Object.keys(object).forEach(function (key) { 
 
     if (object[key] && typeof object[key] === 'object') { 
 
      return getPath(object[key], path.concat(key)); 
 
     } 
 
     console.log(path.concat([key,object[key]]).join('/')); 
 
    }); 
 
} 
 

 
var data = { A: { B: { e: "1", f: { g: "2", h: "3" }, C: { i: "4", j: "5", k: "6", l: "7" }, D: { m: "8", n: "9", o: "10", p: "11" } } } }; 
 
getPath(data);
.as-console-wrapper { max-height: 100% !important; top: 0; }

0

刪除從代碼返回語句使得它爲我工作。

https://jsbin.com/deqelaj/edit?html,js,console

var assets = []; 

function build(json, path, assets){ 
for (var elem in json) { 
    if(json.hasOwnProperty(elem)){ 
    if(json[elem] == 0){ 
     assets.push(elem); 

      //do stuff with the array 


     assets.pop(); 

     } else { 
     var parent = path + '/' + elem; 
     assets.push(parent); 
     console.log(assets) 
     build(json[elem], parent, assets); 
     } 
    } 
    } 
    } 


var json = { 
    "A": { 
     "B": { 
      "e": "", 
      "f": { 
       "g": "", 
       "h": "" 
      }, 
      "C": { 
       "i": "", 
       "j": "", 
       "k": "", 
       "l": "" 
      }, 
      "D": { 
       "m": "", 
       "n": "", 
       "o": "", 
       "p": "" 
      } 
     } 
    } 
    } 


build(json, '', assets); 

console.log(assets) 
+0

它工作到某一點,檢查https://jsbin.com/wifiyagoga/edit?html,js,console它添加了它不是父母在最後步驟中的元素,但返回語句已修復,但它不會爲每個元素構建數組。 –

+0

更新:我認爲刪除返回並添加assets.pop();建立後(json [elem],父母,資產);解決它 –

0

使用reduceconcat

const build = (data, path = []) => 
 
    data == null 
 
    ? [] 
 
    : Object (data) === data 
 
     ? Object.entries (data) .reduce ((acc, [ k, v ]) => 
 
      acc.concat (build (v, [ ...path, k ])), []) 
 
     : [ [ ...path, data ] ] 
 

 
const mydata = 
 
    { A: { B: { e: '1' 
 
      , f: { g: '2' 
 
       , h: '3' 
 
       } 
 
      , C: { i: '4' 
 
       , j: '5' 
 
       , k: '6' 
 
       , l: '7' 
 
       } 
 
      , D: { m: '8' 
 
       , n: '9' 
 
       , o: '10' 
 
       , p: '11' 
 
       } 
 
      } 
 
     } 
 
    } 
 

 
console.log (build (mydata)) 
 
// [ ['A','B','e','1'], 
 
// ['A','B','f','g','2'], 
 
// ['A','B','f','h','3'], 
 
// ['A','B','C','i','4'], 
 
// ['A','B','C','j','5'], 
 
// ['A','B','C','k','6'], 
 
// ['A','B','C','l','7'], 
 
// ['A','B','D','m','8'], 
 
// ['A','B','D','n','9'], 
 
// ['A','B','D','o','10'], 
 
// ['A','B','D','p','11'] ]