【问题标题】:JavaScript recursive function to parse complex JSON object/array用于解析复杂 JSON 对象/数组的 JavaScript 递归函数
【发布时间】:2021-07-08 02:08:16
【问题描述】:

我有一个这样的 JSON 响应:

{
   "data":[
      {
         "type":"node--base_product_coffee",
         "id":"6dbb5a52-13ea-4f74-8af9-eb9e3ba45918",
         "date":"1990",
         "data1":[
            {
               "type1":"product_coffee1",
               "id1":"6dbb5a52-13ea-4f74-8af9-eb9e3ba45777",
               " date1 ":[
                  {
                     "  res ":"  oui "
                  },
                  {
                     "  res ":"  non "
                  }
               ]
            },
            {
               "type1":"product_coffee2",
               "id1":"6dbb5a52-13ea-4f74-8af9-eb9e3ba45666",
               "date1":[
                  {
                     "  res ":"  ouiii "
                  },
                  {
                     "  res ":"  nonnn "
                  }
               ]
            }
         ]
      }
   ]
}

我的目标是能够从像data.data1.date1.res 这样的动态路径中获取值作为列表,以获取结果['oui', 'non', 'ouiii', 'nonnn']

所以我从这个函数开始

parseIt = function(response, s) {
    if (!response) return null;
    if (!s) return obj;


    if (Array.isArray(response)) {
        var data = JSON.parse(JSON.stringify(response));
    } else {
        var data = JSON.parse(response);
    }

    var result = [];
    var path = [];
    
    path = s.split('.');

    if (Array.isArray(data)) {
        for (var i = 0; i < data.length; i++) {
            if (getType(data[i][path[0]]) == 'string') {
                result.push(data[i][path[0]]);
            } else {
                parseIt(data[i][path[i]], path.slice(1).join('.'));
            }

        }
    } else {
        for (var p in data) {
            if (getType(data[p]) == 'string') {
                result.push(data[p]);
            } else {
                parseIt(data[p], path.slice(1).join('.'));
            }
        }
    }
    document.writeln('result=>'+result+'</br>');
    return result;
}

document.writeln(parseIt(response2, 'data.data1.date1.res')+'</br>');

//Console Output
result=>oui,non
result=>
result=>
result=>

但我面临两个问题:

  1. 我只得到 date1.res 元素的结果(即 'oui' 和 'non'),但我需要它的所有元素(即 'oui'、'non'、'ouiii'、'nonnn')
  2. 结果为空(使用递归时如何将结果存储在列表中)

我需要你的帮助,因为我在工作中需要这个,因为我们有像这样的复杂 JSON。

【问题讨论】:

  • 为自己节省一些时间 - 使用flat

标签: javascript arrays json object recursion


【解决方案1】:

您可以通过使用数组展平的递归函数调用来尝试此操作。

const test={"data":[{"type":"node--base_product_coffee","id":"6dbb5a52-13ea-4f74-8af9-eb9e3ba45918","date":"1990","data1":[{"type1":"product_coffee1","id1":"6dbb5a52-13ea-4f74-8af9-eb9e3ba45777","date1":[{"res":"oui"},{"res":"non"}]},{"type1":"product_coffee2","id1":"6dbb5a52-13ea-4f74-8af9-eb9e3ba45666","date1":[{"res":"ouiii"},{"res":"nonnn"}]}]}]};
 

parseIt = function(data, [key, ...path]) {
    return (Array.isArray(data) ? data : [data]).reduce((acc, obj) => {
        if (path.length) {
            acc.push(parseIt(obj[key], path));
        } else if (obj[key]) {
            acc.push(obj[key]);
        }
        return acc;
    }, []).flat();
}

function getValue(response, s) {
    if (!response) return null;
    if (!s) return obj;
    var path = s.split('.');
    return parseIt(response, path).flat();
}

console.log(getValue(test, 'data.data1.date1.res'))

【讨论】:

    【解决方案2】:

    我想还有更好的,

    const test = {
        "data":[
           {
              "type":"node--base_product_coffee",
              "id":"6dbb5a52-13ea-4f74-8af9-eb9e3ba45918",
              "date":"1990",
              "data1":[
                 {
                    "type1":"product_coffee1",
                    "id1":"6dbb5a52-13ea-4f74-8af9-eb9e3ba45777",
                    "date1":[
                       {
                          "res":"oui"
                       },
                       {
                          "res":"non"
                       }
                    ]
                 },
                 {
                    "type1":"product_coffee2",
                    "id1":"6dbb5a52-13ea-4f74-8af9-eb9e3ba45666",
                    "date1":[
                       {
                          "res":"ouiii"
                       },
                       {
                          "res":"nonnn"
                       }
                    ]
                 }
              ]
           }
        ]
     }
     
    
     for(const obj of test.data){
        for(const obj2 of obj.data1){
            for(const obj3 of obj2.date1){
                console.log(obj3.res)
            }
        }
    }

    但你也可以这样做。

    【讨论】:

    • 没有访问数据的路径应该是动态的,这意味着如果我设置一个路径,它会返回该路径中所有值的列表
    【解决方案3】:

    你只需要遍历data.data1

    const res = data.map(elm => {
        // console.log(elm)
        return elm.data1.map(elm => {
            // console.log(elm)
            return elm.date1.map(elm => {
                // console.log(elm)
                return elm.res;
            });
        });
    }).join().split(",");
    
    console.log(res)
    

    这应该让你 ["oui", "non", "ouiii", "nonnn"] 将 .log 留在那里,这样您就不必自己输入它们了...

    【讨论】:

    • 这不是动态路径,您可以随意指定 data 和 data1 和 date1 和 res 。我希望路径是动态的,这意味着我给它一个像“data.data1”或“data.type”这样的路径或任何其他路径,它应该返回该路径中存在的所有值的列表。
    • 您希望它返回所有 res 值吗?
    【解决方案4】:

    最近的一次编辑将这个问题带到了前台。我认为这可以更简单地完成。

    这是一个实现:

    const makeArray = (x) => x ? Array.isArray(x) ? x : [x] : []
    
    const _flatPath = ([p, ...ps]) => (o) =>
      p ? makeArray (o [p]) .flatMap (_flatPath (ps)): makeArray(o)
    
    const flatPath = (path = '') => _flatPath (path.split ('.'))
    
    const input = {data: [{type: "node--base_product_coffee", id: "6dbb5a52-13ea-4f74-8af9-eb9e3ba45918", date: "1990", data1: [{type1: "product_coffee1", id1: "6dbb5a52-13ea-4f74-8af9-eb9e3ba45777", date1: [{res: "oui"}, {res: "non"}]}, {type1: "product_coffee2", id1: "6dbb5a52-13ea-4f74-8af9-eb9e3ba45666", date1: [{res: "ouiii"}, {res: "nonnn"}]}]}]}
    
    console .log (
      flatPath ('data.data1.date1.res') (input)
    )

    makeArray 将值包装在一个数组中。如果它已经是一个数组,则简单地返回。如果它是一个标量值,我们返回一个仅包含该值的数组。如果它为零,我们返回一个空数组。

    我们的主要函数是 _flatPath,它遍历对象的路径(以字符串数组的形式提供),将结果展平为单个数组。

    flatPath 是它的公共门面,将'data.data1.date1.res' 之类的字符串拆分为数组['data', 'data1', 'date1', 'res'] 以传递给_flatPath


    注意,我假设问题输入中围绕键和值的额外空格只是拼写错误。如果您确实有看起来像 ' res ' 的密钥,但想用 'res' 找到它们,那么还有一些工作要做。

    【讨论】:

      猜你喜欢
      • 2020-02-27
      • 2019-08-28
      • 1970-01-01
      • 1970-01-01
      • 2016-07-08
      • 1970-01-01
      • 1970-01-01
      • 2019-08-28
      • 1970-01-01
      相关资源
      最近更新 更多