'Convert string with dot notation to JSON

Given a string as dot notation, how would I create an object from that string (checking for already existing properties): eg

var obj = {};
stringToObj('a.b', 'value1', obj);
stringToObj('a.b.c', 'value2', obj);

would produce

{
   "a": {
    "b": {
        "_x": "value1",
        "c": {
            "_x": "value2"
        }
    }
    }
 }

I've looked at this question and this one but neither seems to be sufficient for what Im doing.

Any thoughts?



Solution 1:[1]

For those of you who are looking for solution without the _x in the object try this code. A slight modification of the above code (which is brilliant)

stringToObj = function(path,value,obj) {
  var parts = path.split("."), part;
  var last = parts.pop();
  while(part = parts.shift()) {
   if( typeof obj[part] != "object") obj[part] = {};
   obj = obj[part]; // update "pointer"
  }
 obj[last] = value;
}

As bonus the above code will work if you want to update parts of an existing object :)

 var obj = {a:{b:3}};
 stringToObj("a.b",10,obj);
 console.log(obj); //result : {a:{b:10}}

Solution 2:[2]

To expand on both @ilikeopensource and @Niet the Dark Absol answers, I needed to add the support for arrays (multiple instances of the same path) with the possibility for nested objects. My case was more of a hybrid of dot notation and json strings.

function stringToObj(path, value, obj) {
    var objValue = value;
    try {
        objValue = JSON.parse(value);
    } catch (e) { } //eat the error, must not be json so carry on... Hack to do a valid JSON check

    var parts = path.split("."), part;
    var last = parts.pop();
    while (part = parts.shift()) {
        if (typeof obj[part] != "object")
            obj[part] = {};
        obj = obj[part];
    }
    if (obj.hasOwnProperty(last) && obj[last] && obj[last].constructor === Array) {
        obj[last].push(objValue);
    }
    else if (obj.hasOwnProperty(last) && obj[last]) {
        var objArray = [];
        objArray.push(obj[last])
        objArray.push(objValue);
        obj[last] = objArray;
    }
    else {
        obj[last] = objValue;
    }
}

Thanks guys for the help!

Solution 3:[3]

This may be well answered already, but I would like to share my resolution for those who still looking for a different approach.

If you would like to convert string dot notation to a string JSON, here's my approach.

function dotToJson({ notation, inclusive = true, value = null }) {
  const fragments = notation.split(".").reverse();

  if (!inclusive) {
    fragments.pop();
  }

  console.log(fragments);

  return fragments.reduce((json, fragment) => {
    if (isNaN(fragment)) {
      return `{ "${fragment}": ${json} }`
    }

    let fill = "";

    if (Number(fragment) > 0) {
      for (let i = 0; i < fragment; i++) {
        fill += "null, "
      }
    }

    return `[${fill}${json}]`;
  }, JSON.stringify(value));
};
Attribute Meaning
notation Dot notation string
inclusive Include the root fragment
value Default value for leaf

You can see the results here, I tested it using Quokka.js

Final screenshot

NOTE: Additionally to this, thiss may help to update objects because you can use spread operator with the parsed version of the JSON

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2
Solution 3