'Js or ES6 Get object field by path string when field has 2 or more nested levels as in myObj.one.two.three.field [duplicate]

If I have a base object which is always the same: project but sometimes I have to access its fields dynamically, how can I access its fields when it can be 1 or more nested objects for example:

function (myPath){
  return project[myPath];

}

This works when using project["oneField"] in myPath("oneField")

but it does not work when it is nested to or more levels:

myPath("one.two.fieldName") does not work: project["one.two.fieldName"]

Neither like this: project."one.two.fieldName"



Solution 1:[1]

You could do it like this (ES6):

function getVal(object, path){
    return path.split('.').reduce ( (res, prop) => res[prop], object );
}

// sample data
var object = { one: { two: { fieldName: 'gotcha' } } };

// get inner field value
console.log( getVal(object, 'one.two.fieldName') );

You can further extend this function to also support square brackets:

function getVal(object, path){
    const regex = /(?<=\[)(?!")[^\]]+|(?<=\[")[^"]+|[^."[\]]+/g;
    return path.match(regex).reduce ( (res, prop) => res[prop], object );
}

let object = { 'a': [{ 'b': { 'c': 3 } }] };
console.log( getVal(object, 'a[0].b["c"]') );

Solution 2:[2]

Usually if I'm doing something like this, I'll use a recursive function:

var data = {a: {b: {c: 5}}};

function getValue(obj, key) {
    var parts = key.split('.');
    return obj 
        && (parts.length === 1 
            && obj[key] || getValue(obj[parts[0]], parts.slice(1).join('.'))) 
    || null;
}

console.log(getValue(data, "a.b.c"));

JSFiddle

It's a bit concisely written, but basically if it has a key with a dot in it, it'll call it down a level. If it ever gets an obj that doesn't exist, it'll return null. Otherwise, once it's down to the last level, it'll return the value it found.

A more expanded, maybe easier to understand, version is:

function getValue(obj, key) {
    var parts = key.split('.');
    if (!obj) {
        return null;
    } else if (parts.length === 1) {
        return obj[key];
    }

    return getValue(obj[parts.slice(1).join('.')], key);
}

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 samanime