Home > OS >  Convert dot separated String into nested JSON object in Angular/Typescript
Convert dot separated String into nested JSON object in Angular/Typescript

Time:10-01

So I was trying this for hours now, needed some help.

I have a string with dots which I need to convert into a nested JSON Objects.

    data=
  "REPM.Action.Portfolio.budget.repairDetails.excelExport" "." 
  "REPM.Action.Portfolio.bsc.list.keyCalculate" "." 
  "REPM.Action.Portfolio.bsc.Overview.keyLoad" "." 
  "REPM.Action.Portfolio.budget.versionSelection.createVersion" "." 
  "REPM.Action.Portfolio.dcf.dcfCompare.keyExportWorksheet" "." 
  "REPM.Action.Portfolio.dcf.keyRateCompare.keyExportWorksheet" "." 
  "REPM.Action.Portfolio.dcf.keyScenario.keyClone" "." 
  "REPM.Action.Portfolio.dcf.keyScenario.keyDelete" "." 
  "REPM.Action.Portfolio.dcf.keyScenario.keyNewCalculation" "." 
  "REPM.Action.Portfolio.dcf.keyScenario.keyNewMandate" "." 
  "REPM.Action.Portfolio.dcf.keySelection.keyDefinitive";

And the output is expected to look something like this

{
"REPM": {
  "Action": {
    "Portfolio": {
      "budget": {
        "repairDetails": {
          "excelExport": null
        },
        "versionSelection": {
          "createVersion": null
        }
      },
      "bsc": {
        "list": {
          "keyCalculate": null
        },
        "Overview": {
          "keyLoad": null
        }
      },
      "dcf": {
        "dcfCompare": {
          "keyExportWorksheet": null
        },
        "keyRateCompare": {
          "keyExportWorksheet": null
        },
        "keyScenario": {
          "keyClone": null,
          "keyDelete": null,
          "keyNewCalculation": null,
          "keyNewMandate": null,
        },
        "keySelection": {
          "keyDefinitive": null
        }

      }
    }
  }
}

}

Currently I have tried...

var tempObject = {};
    var value = this.receivedString.split('.')
    console.log(value.length)
    var curr = tempObject;
    for (var i = 0; i < value.length; i  ) {
      var next = {}
      curr[value[i]] = next;
      curr = next;
    }

  }

This is giving me a flat object with basically each object inside another, with repeated properties.

    {
    "REPM":{
      "Action":{
        "Portfolio":{
          "budget":{
            "repairDetails"{
              "excelExport":{
                "REPM":{
                  "Action":{
                    "Portfolio":{ //and so on...
                    }
                  }
                }
              }
            }

          }
        }
      }
    }
  }

would appreciate some help, thanks.

CodePudding user response:

Well, here it is, but this algorithm is a little advanced. It might take some time to wrap your head around. Let me know if my explanation doesn't make sense.

  1. You need to create an empty JavaScript object.
  2. Walk down the string, entry by entry.
  3. On new property names, you create a new object at your current position in the JavaScript object. This object becomes your new nesting 'level'.
  4. On recurring property names, you jump up to that level in your JavaScript object.

(Once you're done, you convert any empty objects to null, which actually takes more lines of code.)

const data =
  "REPM.Action.Portfolio.budget.repairDetails.excelExport" "." 
  "REPM.Action.Portfolio.bsc.list.keyCalculate" "." 
  "REPM.Action.Portfolio.bsc.Overview.keyLoad" "." 
  "REPM.Action.Portfolio.budget.versionSelection.createVersion" "." 
  "REPM.Action.Portfolio.dcf.dcfCompare.keyExportWorksheet" "." 
  "REPM.Action.Portfolio.dcf.keyRateCompare.keyExportWorksheet" "." 
  "REPM.Action.Portfolio.dcf.keyScenario.keyClone" "." 
  "REPM.Action.Portfolio.dcf.keyScenario.keyDelete" "." 
  "REPM.Action.Portfolio.dcf.keyScenario.keyNewCalculation" "." 
  "REPM.Action.Portfolio.dcf.keyScenario.keyNewMandate" "." 
  "REPM.Action.Portfolio.dcf.keySelection.keyDefinitive";

function recurrentDotSplit( data ) {

    const keys = {};
    let result = null, level = null;

    const entries = data.split( '.' );

    for( const entry of entries ) {

        if( ! keys[ entry ] ) {
            keys[ entry ] = {};
            if( level ) level[ entry ] = keys[ entry ]
        }
        if( ! result ) result = { [ entry ]: keys[ entry ] };
        level = keys[ entry ];

    }


    const ennulled = new Set();

    function ennull( o ) {

        if( ennulled.has( o ) ) return o;

        ennulled.add( o );

        const keys = Object.keys( o );

        if( keys.length === 0 ) return null;

        Object.keys( o ).forEach( key => o[ key ] = ennull( o[ key ] ) );

        return o;

    }

    ennull( result );

    
    return result;

}

var objectStructure = recurrentDotSplit( data );

console.log( objectStructure );
  • Related