You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用JavaScript从JSON提取URL并构建部落小队层级结构

问题描述

我有如下JSON测试报告数据:

[
  {
    "line": 1,
    "elements": [
      {
        "start_timestamp": "2022-10-17T20:07:41.706Z",
        "steps": [
          {
            "result": { "duration": 12216552000, "status": "passed" },
            "line": 5,
            "name": "m0e",
            "match": { "location": "seleniumgluecode.book.user_is_on_homepagee()" },
            "keyword": "Given "
          },
          {
            "result": { "duration": 2074982200, "status": "passed" },
            "line": 6,
            "name": "m1e1",
            "match": { "location": "seleniumgluecode.book.user_enters_Usernamee()" },
            "keyword": "When "
          }
        ],
        "tags": [{ "name": "@Smokee" }]
      },
      {
        "start_timestamp": "2022-10-17T20:08:12.284Z",
        "steps": [
          {
            "result": { "duration": 12090584100, "status": "passed" },
            "line": 12,
            "name": "m0e2",
            "match": { "location": "seleniumgluecode.book2.user_is_on_homepageee()" },
            "keyword": "Given "
          }
        ],
        "tags": [{ "name": "@Smokee" }]
      }
    ],
    "name": "Login Featuree",
    "description": "  Verify if user is able to Login in to the sitee",
    "id": "login-featuree",
    "keyword": "Feature",
    "uri": "file:src/test/java/features/tribe1/squad1/kitab.feature",
    "tags": []
  },
  {
    "line": 1,
    "elements": [
      {
        "start_timestamp": "2022-10-17T20:08:34.480Z",
        "steps": [
          {
            "result": { "duration": 11366098500, "status": "passed" },
            "line": 5,
            "name": "m0e",
            "match": { "location": "seleniumgluecode.book.user_is_on_homepagee()" },
            "keyword": "Given "
          }
        ],
        "tags": [{ "name": "@Smokee" }]
      }
    ],
    "name": "Login Featureefghfgh",
    "description": "  Verify if user is able to Login in to the sitee",
    "id": "login-featureefghfgh",
    "keyword": "Feature",
    "uri": "file:src/test/java/features/tribe1/squad2/kitab2.feature",
    "tags": []
  },
  {
    "line": 19,
    "elements": [
      {
        "start_timestamp": "2022-10-17T20:09:40.836Z",
        "steps": [
          {
            "result": { "duration": 12761711100, "status": "passed" },
            "line": 23,
            "name": "m0e",
            "match": { "location": "seleniumgluecode.book.user_is_on_homepagee()" },
            "keyword": "Given "
          }
        ],
        "tags": [{ "name": "@Smokee" }]
      }
    ],
    "name": "X Feature",
    "description": "  Verify if user is able to Login in to the sitee",
    "id": "login-featuree",
    "keyword": "Feature",
    "uri": "file:src/test/java/features/tribe2/test.feature",
    "tags": []
  }
]

我用下面的JS代码提取URI地址:

document.addEventListener("DOMContentLoaded", () => {
    var i = report.length;
    var array = [];
    for(x = 0; x < i; x++){
        array.push(report[x].uri.split("/"));
    }
    console.log(array2); // 此处笔误,应为array
});

得到的结果是:

[
  ['file:src', 'test', 'java', 'features', 'tribe1', 'squad1', 'kitab.feature'],
  ['file:src', 'test', 'java', 'features', 'tribe1', 'squad2', 'kitab2.feature'],
  ['file:src', 'test', 'java', 'features', 'tribe2', 'test.feature']
]

我需要移除file:src、test、java、features这四个前缀,得到:

[
  ['tribe1', 'squad1', 'kitab.feature'],
  ['tribe1', 'squad2', 'kitab2.feature'],
  ['tribe2', 'test.feature']
]

最终要根据这些路径段构建层级结构:如果.feature文件前有两个元素,第一个是部落(tribe)、第二个是小队(squad);如果只有一个元素,那就是部落直接对应feature。结构示例如下:

[tribe1
    squad1
        elem 
             1
             2
        name: Login Featuree
        url: file:src/test/java/features/tribe1/squad1/kitab.feature
    squad2
        elem 
             1
        name: Login Featureefghfgh
        url: file:src/test/java/features/tribe1/squad2/kitab2.feature
tribe2
    elem 
         1
    name: X Feature
    url: file:src/test/java/features/tribe2/test.feature
]
解决方案

1. 移除URI前缀,提取目标路径段

直接用数组的slice方法去掉前4个元素即可,修正后的提取代码如下:

document.addEventListener("DOMContentLoaded", () => {
    const pathSegmentsArray = report.map(item => {
        // 分割URI后,去掉前4个前缀元素
        return item.uri.split("/").slice(4);
    });
    console.log(pathSegmentsArray);
    // 后续层级构建逻辑写在这里
});

运行后就能得到你想要的路径段数组。

2. 构建部落-小队的层级结构

用一个对象来存储最终的层级数据,遍历每个测试报告项,解析路径段中的部落、小队、feature信息,同时把对应的name、uri、elements(步骤数)关联进去:

document.addEventListener("DOMContentLoaded", () => {
    const hierarchy = {};

    report.forEach(item => {
        const pathSegments = item.uri.split("/").slice(4);
        let tribe, squad, featureName;

        // 解析路径段
        if (pathSegments.length === 3) {
            // 格式:[tribe, squad, feature]
            tribe = pathSegments[0];
            squad = pathSegments[1];
            featureName = pathSegments[2];
        } else if (pathSegments.length === 2) {
            // 格式:[tribe, feature]
            tribe = pathSegments[0];
            squad = null;
            featureName = pathSegments[1];
        }

        // 初始化部落节点
        if (!hierarchy[tribe]) {
            hierarchy[tribe] = { squads: {}, features: [] };
        }

        // 收集feature的信息:元素数量(elements的长度)、name、uri
        const featureInfo = {
            elemCount: item.elements.length,
            name: item.name,
            url: item.uri
        };

        // 区分有小队和无小队的情况
        if (squad) {
            // 初始化小队节点
            if (!hierarchy[tribe].squads[squad]) {
                hierarchy[tribe].squads[squad] = { features: [] };
            }
            hierarchy[tribe].squads[squad].features.push(featureInfo);
        } else {
            hierarchy[tribe].features.push(featureInfo);
        }
    });

    // 格式化输出成你要的结构
    const formattedOutput = Object.entries(hierarchy).map(([tribe, data]) => {
        let output = `${tribe}\n`;
        
        // 处理小队
        if (Object.keys(data.squads).length > 0) {
            Object.entries(data.squads).forEach(([squad, squadData]) => {
                output += `    ${squad}\n`;
                squadData.features.forEach(feature => {
                    output += `        elem\n`;
                    // 生成elem的序号(1到elemCount)
                    for (let i = 1; i <= feature.elemCount; i++) {
                        output += `             ${i}\n`;
                    }
                    output += `        name: ${feature.name}\n`;
                    output += `        url: ${feature.url}\n`;
                });
            });
        }

        // 处理无小队的feature
        if (data.features.length > 0) {
            data.features.forEach(feature => {
                output += `    elem\n`;
                for (let i = 1; i <= feature.elemCount; i++) {
                    output += `         ${i}\n`;
                }
                output += `    name: ${feature.name}\n`;
                output += `    url: ${feature.url}\n`;
            });
        }

        return output;
    }).join("");

    console.log(formattedOutput);
});

运行结果

上述代码运行后,会输出你想要的层级结构:

tribe1
    squad1
        elem
             1
             2
        name: Login Featuree
        url: file:src/test/java/features/tribe1/squad1/kitab.feature
    squad2
        elem
             1
        name: Login Featureefghfgh
        url: file:src/test/java/features/tribe1/squad2/kitab2.feature
tribe2
    elem
         1
    name: X Feature
    url: file:src/test/java/features/tribe2/test.feature

内容的提问来源于stack exchange,提问作者CRYPTO

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 08:25:34