2016-09-17 80 views
6

Próbuję spłaszczyć obiekt, w którym klucze będą pełną ścieżką do węzła liścia. Potrafię rekurencyjnie zidentyfikować, które są węzłami liści, ale utknąłem próbując zbudować całą ścieżkę.Pełna ścieżka obiektu json

próbki wejściowe:

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

wyjściowa:

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

Można zobaczyć tę odpowiedź: http://stackoverflow.com/questions/19098797/fastest-way-to-flatten-un-flatten-nested-json-objects nadzieję, że może Ci pomóc. –

+0

Dlaczego tego chcesz? – Victor

+1

@Victor Wykonuję połączenia api takie jak api.moviestore.com/movies?where[movie.name:eq]=grawitacja. Muszę spłaszczyć obiekt, aby utworzyć zapytanie filtru. – Sayem

Odpowiedz

9

Można użyć rekurencyjnej approch i zbierać klucze do obiektu. Ta propozycja również szuka tablic.

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

Korzystanie z najnowszych funkcji JS jak rozprzestrzenianie obiekt i Object.entries powinno być dość proste:

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

Należy pamiętać, że ten kod nie jest prawdopodobnie najbardziej optymalna jako to kopie obiekt za każdym razem, gdy chcemy go scalić. Traktuj to bardziej jako istotę tego, jak by wyglądał, a nie jako kompletne i ostateczne rozwiązanie.

0

Częściowe rozwiązanie: Daj wejście jako pełną ścieżkę do funkcji i daje odpowiednie wyjście

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

Non fantazyjne podejście, wewnętrznie używa rekursji.

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

Można po prostu zrobić w następujący sposób;

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