Return 对象中每个深度 属性 的字符串路径数组

Return array of string paths to every deep property within an object

我有一个丑陋的 1MB+ JSON 对象,它具有许多深层属性,包括包含嵌套对象的嵌套数组等。

我正在寻找一个函数,它可以 return 一个字符串数组 "paths" 用于给定对象中的每个 属性。

['obj.propA.first', 'obj.propA.second', 'obj.propB']

到目前为止,我的所有搜索都找到了另一个方向的解决方案。例如:获取路径字符串并获取 属性 值。

我的直觉告诉我必须有比重新发明轮子更好的方法。

提前致谢!

示例行为:

var ugly = {
  a: 'a',
  b: ['b1', 'b2'],
  c: {
    c1: 'c1',
    c2: ['c2a', 'c2b'],
    c3: {
      c3a: 'c3a',
      c3b: [['c3b']],
    },
    c4: [{c4a: 'c4a'}],
  }
};

getPaths = function(obj) {
      ???
};    

getPaths(ugly) = [
      'a',
      'b[0]',
      'b[1]',
      'c.c1',
      'c.c2[0]',
      'c.c2[1]',
      'c.c3.c3a',
      'c.c3.c3b[0][0]',
      'c.c4[0].c4a',
    ];

这种情况有点奇怪,大概是在暗示架构层面有问题,但要明白那些东西有时是继承的and/or不可避免的。

node 4.2 版本的 es2015 中一个非常糟糕的可变递归实现:

function isPlainishObject(obj) {
  return Object.prototype.toString.call(obj) === '[object Object]';
}

function propinator (obj, _paths, _currentPath) {
  _paths = _paths || [];

  if (typeof obj !== 'object') {
    _paths.push(_currentPath);
  } else {
    for (let prop in obj) {
      let path;
      if (isPlainishObject(obj)) {
        path = _currentPath && `${_currentPath}.${prop}` || prop;
      } else {
        path = _currentPath && `${_currentPath}[${prop}]` || prop;
      }

      propinator(
        obj[prop],
        _paths,
        path
      );
    }
  }

  return _paths;
}

测试:

let assert = require('assert');
assert.deepEqual(propinator(ugly), [
  'a',
  'b[0]',
  'b[1]',
  'c.c1',
  'c.c2[0]',
  'c.c2[1]',
  'c.c3.c3a',
  'c.c3.c3b[0][0]',
  'c.c4[0].c4a',
]);    

jsbin

这只是轻微测试(虽然可能很差)所以非常欢迎opinions/improvements。