0

Suppose I have a string that references a deep Javascript object, such as:

var string = 'response.basicInfo.gender';

I want to build a function that safely checks if that object exists, by splitting the string by .s and building the object, checking each level as it goes, and then dealing with the value of the object, if it actually exists.

var parseHelper = function(response, items) {
  for (item in items) {
    var parts = String(item).split('.');
    for (var i = 0; i < parts.length; ++i) {
      // ... etc. build the string
    }
  }
}

parseHelper(response, {
  'basicInfo.gender': function(val){
    return (val == 'M') ? 'Male' : (val == 'F') ? 'Female' : val;
  },
})

While the above function is incomplete, let's suppose we use it to build the string and check if each exists:

// so let's suppose we build the string:
var builtString = "response['basicInfo']";

// Now we want to check if it exists 
if (response['basicInfo']) {

  // And if we are fine that it exists, go on to the next item
  var builtString = "response['basicInfo']['gender']";

  // etc.
}

I don't have a problem building that function, I just don't know how to evaluate a string like "response['basicInfo']['gender']" and turn it into an actual reference to the object. My only guess would be eval(), but eval is evil...

Update

I know you can reference a global object by going window['blah'], but this response object I want to reference is not in the global scope, so do I use this? And even if I can do this, how do I reference it with multiple layers?

Community
  • 1
  • 1
dthree
  • 19,847
  • 14
  • 77
  • 106
  • You cannot without `eval`. You need a base object (`response` in your case) *and* a property list. – Bergi Sep 23 '13 at 16:21
  • Can you give me some sort of code sample? – dthree Sep 23 '13 at 16:22
  • 1
    [There are many](http://stackoverflow.com/a/14397052/1048572). All of these functions take an object for the base reference and a string (or list of strings) for the properties. – Bergi Sep 23 '13 at 16:24

1 Answers1

0

Plus 1 to Bergi, who linked to a page with six links, one of which had an answer I adapted to solve the problem:

Convert JavaScript string in dot notation into an object reference

Here's the full solution.

// We want to run a parse function to convert
// the object response.basicInfo.gender (which is 'M')
// to 'Male', etc.

// Sets the value of a string representing a deep object.
setDeep: function(root, path, value) {
  var parts = path.split('.'), obj = root;
  for (var i = 0; i < parts.length - 1; ++i) {
    obj = obj[parts[i]] || { };
  }
  obj[parts[parts.length - 1]] = value;
  return obj;
},

// Gets the value of a string representing a deep object.
getDeep: function(root, path) {
  var parts = path.split('.'), obj = root, target;
  for (var i = 0; i < parts.length; ++i) {
   target = obj[parts[i]];
   if (typeof target == "undefined") return void 0;
   obj = target;
  }
  return obj;
},

// Loops through multiple string representations
// of deep objects and runs the values through 
// assigned parsing functions for each of them,
// returning the root object.
parseHelper: function(obj, items) {
  for (item in items) {
    var val = getDeep(obj, item);
    var func = items[item];
    if (val !== undefined) {
      val = func(val);
    }
    setDeep(obj, item, val);
  }
  return obj;
},

// response.basicInfo.gender = 'M';
// response.foo.bar = true;

response = parseHelper(response, {
  'basicInfo.gender': function(val){
    return (val == 'M') ? 'Male' : (val == 'F') ? 'Female' : val;
  },
  'foo.bar': function(val) {
    return (val) ? false : true;
  },
});

// response.basicInfo.gender = 'Male';
// response.foo.bar = false;
Community
  • 1
  • 1
dthree
  • 19,847
  • 14
  • 77
  • 106