Search code examples
javascriptangulartypescriptlodash

Typescript - Complex Object merge with Dot Notation


I want to display the data in a Tree View in Angular and need to transform an array of dot-notated elements into a collection of objects with children.

This is the array I'm working with. Notice the key field in every element.

So the structure I need is for example (for the first 4 elements in the array):

    const data = [
    {
        key: 'bs',
        children: [
            {
                key: 'ass',
                children: [
                    {
                        key: 'fixAss',
                        decimals: '0',
                        unitRef: 'unit_euro',
                        contextRef: 'period_2019',
                        value: 15542000,
                        children: [
                            {
                                key: 'intan',
                                decimals: '0',
                                unitRef: 'unit_euro',
                                contextRef: 'period_2019',
                                value: 8536000,
                                children: [
                                    {
                                        key: 'concessionBrands',
                                        decimals: '0',
                                        unitRef: 'unit_euro',
                                        contextRef: 'period_2019',
                                        value: 8536000,
                                        children: [] // If there are no children in the element this can be empty or left out
                                    }
                                ]
                            },
                            {
                                key: 'tan',
                                decimals: '0',
                                unitRef: 'unit_euro',
                                contextRef: 'period_2019',
                                value: 6890000,
                                children: []
                            }
                        ]
                    }
                ]
            }
        ]
    }
];

That means elements are combined by having a key attribute which holds the notation for that level (i.e "bs", "ass", "fixAss", ...) and then children of the next level. An element can have values of its own ("decimals", "unitRef",...) and might additionally also have children that are made up the same way. There is no restriction on the amount of levels this can have.

I have the lodash and dot object libraries in my package.json. Any help is very much appreciated.


Solution

  • it seems the dot-object lib has no things to work with something like "children" that you have, so it seems custom code is required to build what you expected

    // balanceData got somehow
    
    let data = [];
    const getOrBuildPathObject = (path) => {
       let currentLevel = data;
       let obj = null;
       for(let keyFragment of path.split('.')) {
          obj = currentLevel.find(v => v.key == keyFragment);
          if(!obj) {
            obj = {key: keyFragment, children: []};
            currentLevel.push(obj);
          }
          currentLevel = obj.children;
       }
       return obj;
    }
    
    balanceData.forEach((d) => {
      let {key, ...data} = d;
      Object.assign(getOrBuildPathObject(key), data);
    })
    
    

    should be something like that