2016-09-17 59 views
6

我正在嘗試拼合一個對象,其中的鍵將是葉節點的完整路徑。我可以遞歸地識別哪些是葉節點,但是試圖構建整個路徑。json對象的完整路徑

樣品輸入:

 
{ 
    one: 1, 
    two: { 
    three: 3 
    }, 
    four: { 
    five: 5, 
    six: { 
     seven: 7 
    }, 
    eight: 8 
    }, 
    nine: 9 
} 

輸出:

 
{ 
    one: 1, 
    'two.three': 3, 
    'four.five': 5, 
    'four.six.seven': 7, 
    'four.eight': 8, 
    nine: 9 
} 
+0

你可以看到這樣的回答:http://stackoverflow.com/questions/19098797/fastest-way-to-flatten-un-flatten-nested-json-objects 希望它可以幫你。 –

+0

你爲什麼要這樣? – Victor

+1

@Victor我正在做api調用,如api.movi​​estore.com/movies?where[movie.name:eq]=gravity。我需要扁平化一個對象來構造過濾器查詢。 – Sayem

回答

9

你可以使用遞歸計算策略,並收集對象的鑰匙。該建議也查找數組。

function getFlatObject(object) { 
 
    function iter(o, p) { 
 
     if (Array.isArray(o)){ 
 
      o.forEach(function (a, i) { 
 
       iter(a, p.concat(i)); 
 
      }); 
 
      return; 
 
     } 
 
     if (o !== null && typeof o === 'object') { 
 
      Object.keys(o).forEach(function (k) { 
 
       iter(o[k], p.concat(k)); 
 
      }); 
 
      return; 
 
     } 
 
     path[p.join('.')] = o; 
 
    } 
 

 
    var path = {}; 
 
    iter(object, []); 
 
    return path; 
 
} 
 

 
var obj = { one: 1, two: { three: 3 }, four: { five: 5, six: { seven: 7 }, eight: 8 }, nine: 9 }, 
 
    path = getFlatObject(obj); 
 
\t 
 
console.log(path);

0

使用最新的JS功能,如對象傳播和Object.entries它應該是很容易的:

function flatObj(obj, path = []) { 
    let output = {}; 

    Object.entries(obj).forEach(([ key, value ]) => { 
     const nextPath = [ ...path, key ]; 

     if (typeof value !== 'object') { 
      output[nextPath.join('.')] = value; 

      return; 
     } 

     output = { 
      ...output, 

      ...flatObj(value, nextPath) 
     }; 
    }); 
} 

請注意,此代碼可能不是最優的一個,因爲它拷貝每次我們想要合併它的對象。更多地將它看作是它看起來像什麼的主旨,而不是一個完整的最終解決方案。

0

部分解決: 給輸入的完整路徑的功能,它爲您提供了相應的輸出

var obj = { 
    one: 1, 
    two: { 
    three: 3 
    }, 
    four: { 
    five: 5, 
    six: { 
     seven: 7 
    }, 
    eight: 8 
    }, 
    nine: 9 
}; 

function deepFind(obj, path) { 
    var paths = path.split('.') 
    , current = obj 
    , i; 

    for (i = 0; i < paths.length; ++i) { 
    if (current[paths[i]] == undefined) { 
     return undefined; 
    } else { 
     current = current[paths[i]]; 
    } 
    } 
    return current; 
} 

console.log(deepFind(obj, 'four.six.seven')) 
1

var obj = { 
 
    one: 1, 
 
    two: { 
 
    three: 3 
 
    }, 
 
    four: { 
 
    five: 5, 
 
    six: { 
 
     seven: 7 
 
    }, 
 
    eight: 8 
 
    }, 
 
    nine: 9 
 
}; 
 

 
function flatten(obj) { 
 
    var flatObj = {} 
 

 
    function makeFlat(obj, path) { 
 
    var keys = Object.keys(obj); 
 
    if (keys.length) { 
 
     keys.forEach(function (key) { 
 
     makeFlat(obj[key], (path ? path + "." : path) + key); 
 
     }) 
 
    } else { 
 
     flatObj[path] = obj; 
 
    } 
 
    } 
 
    makeFlat(obj, ""); 
 
    return flatObj; 
 
} 
 

 
console.log(flatten(obj));

0

非花哨做法,內部使用遞歸。

var x = { one:1,two:{three:3},four:{five: 5,six:{seven:7},eight:8},nine:9}; 
 
var res = {}; 
 
var constructResultCurry = function(src){ return constructResult(res,src); } 
 
     
 
function constructResult(target, src) { 
 
    if(!src) return; 
 
    target[src.key] = src.val; 
 
} 
 
     
 
function buildPath(key, obj, overAllKey) { 
 
    overAllKey += (overAllKey ? "." : "") + key; 
 
    if(typeof obj[key] != "object") return { key : overAllKey, val : obj[key] }; 
 
    Object.keys(obj[key]).forEach(function(keyInner) { 
 
    constructResultCurry(buildPath(keyInner, obj[key], overAllKey)); 
 
    }); 
 
} 
 
     
 
Object.keys(x).forEach(function(k){ 
 
    constructResultCurry(buildPath(k, x, "")); 
 
}); 
 

 
console.log(res);

0

你可以簡單地做如下;

var obj = {one: 1, two: {three: 3}, four: {five: 5, six: {seven: 7}, eight: 8}, nine: 9}, 
 
flatObj = (o,p="") => { return Object.keys(o) 
 
            .map(k => o[k] === null   || 
 
               typeof o[k] !== "object" ? {[p + (p ? ".":"") + k]:o[k]} 
 
                     : flatObj(o[k],p + (p ? ".":"") + k)) 
 
            .reduce((p,c) => Object.assign(p,c)); 
 
         }; 
 
console.log(flatObj(obj));