Search code examples
javascriptgoogle-chromeobjectnested

Access property value of an object using its full path


I have an object with many nested elements like this

var out = {
   "parentOne":{
      "subParentOne":{
         "childOne":0,
         "childTwo":0
      },
      "subParentTwo":{
         "otherChildOne":0,
         "otherChileTwo":0
      }
   },
   "parentTwo":{
    [...]
   }
}

There are a total of 269 distinct properties in the object.

And I have an array containing the "path" of the property I need to retrieve like this:

var prop = ["parentOne.subParentOne.childOne", "parentOne.subParentTwo.otherChildTwo"]

so this array can contains up to 269 elements.

To access the value of child key I use the following code:

    for (let p in prop) {
        var result = out
        var keys = prop[p].split(".")
        for (let k in keys) {
            result = result[keys[k]]
        }
        // do stuff with the value
    }

But it's highly inefficient so I am looking for a better solution.

Why this doesn't work?

   var result = out["parentOne.subParentOne.childOne"]

So what is the best way to achieve this?

(please note that I'm building my app on top of electron so I'm just interested in a working solution for google chrome)

edit :

forgot to say that object properties can change. Currently, after launching the app, I send a request to a server, get a sample output and parse the result to get available keys with this method :

var availableKeys = []
parseKey(out, '')

function parseKey(object, root) {
        for (let key in object) {
            switch (typeof object[key]) {
                case 'object':
                    parseKey(object[key], (root === '' ? key : root + '.' + key))
                    break
                case 'number':
                    availableKeys.push((root === '' ? '' : root + '.') + key)
                    break
                default:
                    break
            }
        }
    }

Solution

  • but it's highly inefficient...

    No, it isn't. It's a string split followed by a loop accessing a few properties on an object. Other than the overhead of the split (minimal) and the overhead of the loop (minimal), it's as efficient as out.parentOne.subParentOne.childOne.

    Why this doesn't work?

    var result = out["parentOne.subParentOne.childOne"]
    

    Because that's looking for a property with the name parentOne.subParentOne.childOne, which is a perfectly valid property name for a JavaScript object:

    var out = {
      "parentOne.subParentOne.childOne": "here's the value"
    };
    console.log(out["parentOne.subParentOne.childOne"]);

    So what is the best way to achieve this?

    The way you showed in the question, and/or the various ways detailed in the answers to this question, which will all fundamentally come down to splitting the string and then descending through the object hierarchy as the code in your question does.