Home > Blockchain >  A way to convert an object with keys of . seperated strings into a JSON object
A way to convert an object with keys of . seperated strings into a JSON object

Time:11-01

I'm trying to figure out a way to turn and object like this :

{ "test.subtest.pass" : "test passed", "test.subtest.fail" : "test failed" }

into JSON like this:

{ "test": { "subtest": { "pass": "test passed", "fail": "test failed" }}}

sometimes there may be duplicate keys, as above perhaps there would be another entry like "test.subtest.pass.mark"

I have tried using the following method and it works but it's incredibly ugly:

  convertToJSONFormat() {
        const objectToTranslate = require('<linkToFile>');

        const resultMap = this.objectMap(objectToTranslate, (item: string) => item.split('.'));

        let newMap:any = {};

        for (const [key,value] of Object.entries(resultMap)) {
            let previousValue = null;
            // @ts-ignore
            for (const item of value) {
                // @ts-ignore
                if (value.length === 1) {
                    if(!newMap.hasOwnProperty(item)) {
                        newMap[item] = key
                    } // @ts-ignore
                } else if (item === value[value.length - 1]) {
                    if(typeof previousValue[item] === 'string' ) {
                        const newKey = previousValue[item].toLowerCase().replace(/\s/g, '');;
                        const newValue = previousValue[item];

                        previousValue[item] = {};
                        previousValue[item][newKey] = newValue;
                        previousValue[item][item] = key;
                    } else {
                        previousValue[item] = key;
                    }
                } else if (previousValue === null) {
                    if (!newMap.hasOwnProperty(item)) {
                        newMap[item] = {};
                    }
                    previousValue = newMap[item];
                } else {
                    if (!previousValue.hasOwnProperty(item)) {
                        previousValue[item] = {}
                        previousValue = previousValue[item];
                    } else if (typeof previousValue[item] === 'string') {
                        const newValue = previousValue[item];

                        previousValue[item] = {};
                        previousValue[item][item] = newValue;
                    } else {
                        previousValue = previousValue[item];
                    }
                }
            }
        }

        return newMap;
    }

CodePudding user response:

We can utilize recursion to make the code a little less verbose:

function convertToJSONFormat(objectToTranslate) {
  // create object after mapping
  const result = {};
  // iterate each key-value pair on the object to be translated
  Object
    .entries(objectToTranslate)
    .forEach(([path, value]) => {
      // utilize a recursive function to write the value into the object
      addArrayPathToObject(result, path.split("."), value);
    });
  return result;
}

function addArrayPathToObject(root, parts, value) {
  const p = parts.shift();
  // base-case: We attach the value if we reach the last path fragment
  if (parts.length == 0) {
    root[p] = value
    return;
  }
  // general case: check if root[p] exists, otherwise create it and set as new root.
    if(!root[p]) root[p] = {};
   addArrayPathToObject(root[p], parts, value)
}

This function utilizes the fact that objects are pass-by-reference to recursively traverse through the object starting at its root until setting the desired value.

You can add error-handling and other such concerns as necessary for your use.

CodePudding user response:

@Meggan Naude, toJson function copies json object to reference obj for provided keys and value.

const p = { "test.subtest.pass" : "test passed", "test.subtest.fail" : "test failed" };
const result = {} ;
const toJson = (obj, keys, value) => {
      if (keys?.length === 1) {
         obj[keys[0]] = value;
         return obj
      } else {
         const k = keys.splice(0, 1)
         if (k in obj) {
             toJson(obj[k], keys, value)
         } else {
             obj[k] = {};
             toJson(obj[k], keys, value)
         }
         return obj
      }
}

Object.keys(p).forEach(key => toJson(result, key.split('.'), p[key]))
console.log(result);
  • Related