简体   繁体   中英

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.

My current json data is following:

{
  "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).

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.

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!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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