Полный путь объекта 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
}

6 ответов


вы можете использовать рекурсивный подход и собрать ключи объекта. Это предложение также ищет массивы.

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);
	
console.log(path);

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

частичное решение : Дайте вход как полный путь к функции, и он даст вам соответствующий выход

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

использование новейших функций 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)
        };
    });
}

обратите внимание, что этот код, вероятно, не самый оптимальный, поскольку он копирует объект каждый раз, когда мы хотим его объединить. Рассматривайте его скорее как суть того, как он будет выглядеть, а не как полное и окончательное решение.


не причудливый подход, внутренне использует рекурсию.

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

вы можете просто сделать следующее;

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