将字符串路径数组返回到对象中的每个深层属性

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

本文关键字:属性 对象 路径 字符串 数组 返回      更新时间:2023-09-26

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

我正在寻找一个函数,它可以为给定对象中的每个属性返回一个字符串"路径"数组。

['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',
    ];

这种情况有点奇怪,可能暗示了架构级别存在问题,但要明白,这些事情有时是继承的和/或不可避免的。

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

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

这只是经过了轻微的测试(可能很差),因此非常欢迎意见/改进。