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\$
4
  • \$\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
    CommentedJul 23, 2015 at 20:41
  • \$\begingroup\$@Jamal confirmed the title\$\endgroup\$
    – steveblue
    CommentedJul 23, 2015 at 20:58
  • \$\begingroup\$@Joseph the Dreamer added a Fiddle\$\endgroup\$
    – steveblue
    CommentedJul 23, 2015 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\$CommentedJul 23, 2015 at 21:01

1 Answer 1

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\$

    Start asking to get answers

    Find the answer to your question by asking.

    Ask question

    Explore related questions

    See similar questions with these tags.