1
\$\begingroup\$

Given a strings like 'param1.param2.param3' and a value that should be set on the last parameter, is there a better way than the following to dynamically create an Object and reuse the function to create more parameters on the Object, some which may share a parent parameter? This function also assumes every parameter on the parent Object is an Object with parameters. The purpose is to construct a JSON Object dynamically for a PUT/PATCH request.

function(o,prop,val) {
            prop = prop.split('.');
            prop.forEach(function(property,i){
                if(i===0 && typeof(o[property]) === 'undefined'){
                    o[property] = {};
                    if(prop.length === 2){
                        o[prop[0]][prop[1]] = val;
                    }
                }
                else if(i===1 && typeof(o[prop[0]][property]) === 'undefined'){
                    o[prop[0]][property] = {};
                    if(prop.length === 3){
                        o[prop[0]][prop[1]][prop[2]] = val;
                    }
                } else if(i===1 && typeof(o[prop[0]][property]) === 'object'){
                    if(prop.length === 3){
                        o[prop[0]][prop[1]][prop[2]] = val;
                    }
                }
                else if(i===2 && typeof(o[prop[0]][prop[1]][property]) === 'undefined'){
                    o[prop[0]][prop[1]][property] = {};
                    if(prop.length === 4){
                        o[prop[0]][prop[1]][prop[2]][prop[3]] = val;
                    }
                } else if(i===2 && typeof(o[prop[0]][prop[1]][property]) === 'object'){
                    if(prop.length === 4){
                        o[prop[0]][prop[1]][prop[2]][prop[3]] = val;
                    }
                }
            });
            return o;
        };

Here is a Fiddle https://jsfiddle.net/cn25o1vf/

\$\endgroup\$
  • \$\begingroup\$ You might also want to add a demo to prove that this code isn't broken, or at least we can see how it works. \$\endgroup\$ – Joseph Jul 23 '15 at 20:41
  • \$\begingroup\$ @Jamal confirmed the title \$\endgroup\$ – codescholar Jul 23 '15 at 20:58
  • \$\begingroup\$ @Joseph the Dreamer added a Fiddle \$\endgroup\$ – codescholar Jul 23 '15 at 20:58
  • \$\begingroup\$ You may wish to indicate the desired result. For instance, in that fiddle, it adds a property named "another" with an empty object as a value (in JSON: '{ "another": {} }'), whereas I would have expected it to create a property with the string "object", iow: '{ "another": "object" }'. \$\endgroup\$ – Heretic Monkey Jul 23 '15 at 21:01
2
\$\begingroup\$

It seems odd to special-case the string "object" when preparing an object for serialization, so I came up with the following code:

var createObjectFromParam = function (o, prop, val) {
    var parts = prop.split('.');
    var last = o;
    while (parts.length) {
        var part = parts.shift();
        if (parts.length > 0) {
            last[part] = last[part] || {};
            last = last[part];
        } else {
            last[part] = val; // Add conditional expressions here
        }
    }
    return last;
}

The code does the following:

  • Creates a temporary variable (last) to contain the current "level" of the object hierarchy.
  • Loops through the array. Note that while (parts.length) will stop the loop when there are no longer parts in the array.
  • Take the next part of the prop. shift pulls the first element of the array out.
  • If we're not at the last element
    • If the element with the specified name exists at the level, use that
    • If not, create an object at that level
  • Otherwise, add a property with the specified value to the object.
  • Finally, return the created object.

Given the example in the jsFiddle (updated here), this would produce the following structure:

{
    "ready": {
        "set": "go"
    },
    "another": "object",
    "happy": {
        "happy": {
            "joy": "joy",
            "foo": "bar",
            "happy": "happy"
        }
    }
}

To keep that original special-casing, just replace the commented line with something like:

last[part] = val === 'object' ? {} : val === 'undefined' ? : undefined : val;
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.