简体   繁体   English

JavaScript:将 Json 数据数组更改为新格式

[英]JavaScript: Change Json data array into new format

I am trying to work with a json data which needs to be changed in many ways.我正在尝试使用需要以多种方式更改的 json 数据。

My current json data is following:我当前的 json 数据如下:

{
  "file1": {
    "function1": {
      "calls": {
        "105:4": {
          "file": "file2",
          "function": "function5"
        },
        "106:4": {
          "file": "file2",
          "function": "function6"
        }
      },
      "lines1": {
        "123": "102:0",
        "456": "105:8"
      },
      "lines2": {
        "102:0": [
          "102:0"
        ],
        "105:4": [
          "106:4",
          "107:1"
        ],
        "106:4": [
          "107:1"
        ]
      }
    }
  }
}

But I want the data as following:但我希望数据如下:

{
  "name": "program",
  "children": [
    {
      "name": "file1",
      "children": [
        {
          "name": "function1",
          "calls": [
            {
              "line": 105,
              "file": "file2",
              "function": "function5"
            },
            {
              "line": 106,
              "file": "file2",
              "function": "function6"
            }
          ],
          "lines1": [
            102,
            105
          ],
          "lines2": [
            [
              102,
              102
            ],
            [
              105,
              106,
              107
            ],
            [
              106,
              107
            ]
          ],
          "group": 1
        }
      ],
      "group": 1
    }
  ],
  "group": 0
}

Here, number of files and functions are more.在这里,文件和函数的数量更多。 The value of first name is user defined.名字的值是用户定义的。 The group information is depend on the parent-child.组信息取决于父子。 Each file will have a group ascending group number and all the functions inside the file will also have the same group number.每个文件都有一个组升序组号,文件内的所有功能也将具有相同的组号。 For the values for lines the first part before : are taken (104:4 becomes 104).对于 : 之前的第一部分行的值(104:4 变为 104)。

I have tried with following code so far, which is incomplete and not handling group information correctly.到目前为止,我已尝试使用以下代码,该代码不完整且未正确处理组信息。

function build(data) {
    return Object.entries(data).reduce((r, [key, value], idx) => {
      const obj = {
        name: 'program',
        children: [],
        group: 0,
        lines: []
      }

      if (key !== 'lines2) {
        obj.name = key;
        obj.children = build(value)
          if(!(key.includes(":")))
          obj.group = idx + 1;
      } else {
        if (!obj.lines) obj.lines = [];
        Object.entries(value).forEach(([k, v]) => {
          obj.lines.push([k, ...v].map(e => e.split(':').shift()))
        })
      }

      r.push(obj)
      return r;
    }, [])
  }

  const result = build(data);
  console.log(result);

I would really appreciate if you can help me out.如果您能帮助我,我将不胜感激。 Thanks in advance for your time.在此先感谢您的时间。

Assuming the structure of your input is consistenly defined as shown in your question (ie, that no "saftey checks" are needed, etc), then you could approach this using a combination of Object.entries() , Array.map() and spread syntax as shown below.假设您的输入结构如您的问题所示一致定义(即不需要“安全检查”等),那么您可以使用Object.entries()Array.map()传播语法如下所示。

See inline documentation in this code snippet for details on how to achieve that:有关如何实现该目标的详细信息,请参阅此代码片段中的内联文档:

 function transformData(data, programName) { /* Define local parse helper to extract number from NUMBER:STRING format */ const parseHelper = (str) => Number.parseInt(str.split(':')[0]); /* Define local parse helper to extract group number from STRINGNUMBER format */ const parseGroup = (str) => Number.parseInt(str.replace(/^[az]+/,"")) /* Create a root object with specified program name */ return { name : programName, /* Iterate each file name and object entry of input */ children : Object.entries(input).map(([fileName, fileObject]) => { /* Iterate function name and object of current file object */ const fileChildren = Object.entries(fileObject) .map(([functionName, functionObject]) => { /* Iterate function name and object of current file object */ const lines = Object.entries(functionObject) .reduce((target, [functionKey, functionValue]) => { if(functionKey === "calls") { /* If function key is calls, interpret this value as data to be transformed to desired calls object shape */ const calls = Object.entries(functionValue) .map(([callKey, callObject]) => { return { line : parseHelper(callKey), file : callObject['file'], function : callObject['function'] } }); /* Inject calls object into lines result */ return { ...target, calls }; } else { /* Otherwise, interpret this value as data to be transformed to desired lines object shape */ const lineValues = Object.entries(functionValue) .map(([key, value]) => { /* If value is an array, map key/value pair to a nested array in resulting linesValues array */ return Array.isArray(value) ? [key, ...value] .map(parseHelper) : parseHelper(value) }) /* Inject line values into function key of result */ return { ...target, [functionKey] : lineValues } } }, {}); /* Inject lines into function result */ return { name : functionName, ...lines, group : parseGroup(functionName) } }); /* Map file object to name/children pairing */ return { name : fileName, children : fileChildren, group : parseGroup(fileName) } }), group : 0 } } const input = { "file1": { "function1": { "calls": { "105:4": { "file": "file2", "function": "function5" }, "106:4": { "file": "file2", "function": "function6" } }, "lines1": { "123": "102:0", "456": "105:8" }, "lines2": { "102:0": [ "102:0" ], "105:4": [ "106:4", "107:1" ], "106:4": [ "107:1" ] } } } }; console.log(transformData(input, "program"))

Hope that helps!希望有帮助!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM