Search code examples
javascriptarraysjsonloopsstringify

Map Json data by JavaScript


I have a Json data that I want to have in a different format.

My original json data is:

{
  "info": {
    "file1": {
      "book1": {
        "lines": {
          "102:0": [
            "102:0"
          ],
          "105:4": [
            "106:4"
          ],
          "106:4": [
            "107:1",
            "108:1"
          ]
        }
      }
    }
  }
}

And I want to map it as following:

{
  "name": "main",
  "children": [
    {
      "name": "file1",
      "children": [
        {
          "name": "book1",
          "group": "1",
          "lines": [
            "102",
            "102"
          ],
          [
            "105",
            "106"
          ],
          [
            "106",
            "107",
            "108"
          ]
        }
      ],
      "group": 1,

    }
  ],
  "group": 0
}

But the number of books and number of files will be more. Here in the lines the 1st part (before the :) inside the "" is taken ("106:4" becomes "106"). The number from the key goes 1st and then the number(s) from the value goes and make a list (["106", "107", "108"]). The group information is new and it depends on parent-child information. 1st parent is group 0 and so on. The first name ("main") is also user defined.

I tried the following code so far:

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

      if (key !== 'reduced control flow') {
        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);

The group information is not generating correctly. I am trying to figure out that how to get the correct group information. I would really appreciate if you can help me to figure it out.


Solution

  • You could use reduce method and create recursive function to build the nested structure.

    const data = {"info":{"file1":{"book1":{"lines":{"102:0":["102:0"],"105:4":["106:4"],"106:4":["107:1","108:1"]}}}}}
    
    function build(data) {
      return Object.entries(data).reduce((r, [key, value]) => {
        const obj = {}
    
        if (key !== 'lines') {
          obj.name = key;
          obj.children = build(value)
        } 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);