代码之家  ›  专栏  ›  技术社区  ›  Benjamin RD

使用javascript获取每个级别的JSON值

  •  2
  • Benjamin RD  · 技术社区  · 6 年前

    我尝试使用递归函数从一个简单的 json 使用 javascript

    我有这个 杰森 :

    {
      'a': {
        'b': {
          'c': 12,
          'd': 'Hello World'
        },
        'e': [1,2,3]
      }
    }
    

    我的预期结果是:

    {
      'a/b/c': 12,
      'a/b/d': 'Hello World',
      'a/e': [1,2,3]
    }
    

    我正在尝试:

    function getDeepKeys(obj) {
        var keys = [];
        for (var key in obj) {
            keys.push(key);
            if (typeof obj[key] === "object") {
                var subkeys = getDeepKeys(obj[key]);
                keys = keys.concat(subkeys.map(function (subkey) {
                    return key + "/" + subkey;
                }));
            }
        }
        return keys;
    } 
    

    但出于某种原因,它让我:

    a/b/c/d/e/0/1/ 我不知道为什么要加上这些数字。 有人知道我该怎么做吗?

    3 回复  |  直到 6 年前
        1
  •  0
  •   Ele    6 年前

    你可以使用这个功能 Object.keys 要循环对象的键并使用递归,可以更深入地遍历嵌套对象。

    let obj = {'a': {'b': {'c': 12,'d': 'Hello World'},'e': [1,2,3]}},
        result = Object.create(null),
        loop = function (o, arr, result) {
          Object.keys(o).forEach(k => {
            arr.push(k);
            if (typeof o[k] === 'object' && !Array.isArray(o[k])) loop(o[k], arr, result);
            else result[arr.join('/')] = o[k];        
            arr.splice(-1);
          });
        };    
        
    loop(obj, [], result);
    console.log(result);
    .as-console-wrapper { max-height: 100% !important; top: 0; }
        2
  •  3
  •   Mark    6 年前

    我想你可能使事情变得比必要的更复杂了。您可以使用 Array.isArray 和一个非对象( typeof !== 'object )返回路径和值。否则对每个条目重复。 reduce() 很好。将当前路径作为参数传递给递归函数也很方便:

    let obj = {'a': {'b': {'c': 12,'d': 'Hello World'},'e': [1,2,3]}}
    
    function getValues(obj, path = []){
        return (Array.isArray(obj) || typeof obj !== 'object')
        ? {[path.join('/')]: obj}
        : Object.entries(obj).reduce((acc, [key, val]) => 
            Object.assign(acc, getValues(val, path.concat(key)) )
        , {})
        }
        
    
    console.log(getValues(obj))
        3
  •  3
  •   ggorlen Hoàng Huy Khánh    6 年前

    您可以使用一个比递归开销小且不会破坏调用堆栈的显式堆栈进行迭代:

    const pathify = o => {
      const paths = {};
      const stack = [[o, []]];
      
      while (stack.length) {
        const [curr, path] = stack.pop();
        
        for (const k in curr) {
          if (typeof curr[k] === "object" && !Array.isArray(curr[k])) {
            stack.push([curr[k], path.concat(k)]);
          }
          else {
            paths[`${path.join("/")}/${k}`] = curr[k];
          }
        }
      }
      
      return paths;
    };
    
    console.log(pathify({'a':{'b':{'c':12,'d':'Hello World'},'e':[1,2,3]}}));