JS update nested object key with string of key names concatenating with "."

javascript dynamically access nested object property
javascript dynamic object key
es6 object shorthand
javascript object
accessing object properties with variables
javascript object keys
javascript object properties
javascript object set

Lets say that I have this object:

var obj = {
  level1 :{
    level2: {
      level3: {
        title: "winner"
      }
    }
  }
}

Now I want to update the title key using the next string (notice, I have a string, not actual variable) I have: let myString = "level1.level2.level3.title"; // note - myString value comes from $http method or something

Maybe something like this:

obj[myString] = "super-winner";

Unfortunately the above doesn't work.

In addition - sometimes I need to update an undefined object so I need something to make the object to be defined with a new empty object.

For example, If I have the next object:

var obj = {
  level1 : {}
  }
}

I still want to modify the obj with the level3.winner as above.

Reminder: obj[myString] = "super-winner";

How can I do that?

This works

const obj = {
   // level1: {
    //     level2: {
    //         level3: {
    //             title: "winner"
    //         }
    //     }
    // }
}

const myString = "level1.level2.level3.title"; // note - myString value comes from $http method or something

const title = 'super-winner'

myString.split('.')
    .reduce(
        (acc, curr) => {
            if (acc[curr] === undefined && curr !== 'title') {
                acc[curr] = {}
            }

            if (curr === 'title') {
                acc[curr] = title
            }

            return acc[curr]
        }, obj
    );

console.log(obj) // {"level1":{"level2":{"level3":{"title":"super-winner"}}}}

This is zero-dependency solution, i.e. you don't have to use lodash or something bloating the size of your app.

With ES6, we can finally create dynamic variable key in the object declaration Bracket notation (string key) me['name']; // samantha // 3. Bracket notation  I am building some objects in JavaScript and pushing those objects into an array, I am storing the key I want to use in a variable then creating my objects like so: var key = "happyCount"; myArray

Used "reduce" to achieve your desired result. Created a function "updateValue" where in you can pass obj - object to modify, str - property path to alter, value - value to be assigned at the property path

var obj1 = {
  level1 :{
    level2: {
      level3: {
        title: "winner"
      }
    }
  }
}

var obj2 = { level1: {} }

var obj3 = {
  level1 :{
    level2: {
      level3: {
        title: "winner"
      }
    }
  }
}

function updateValue(obj, str, value) {
let props = str.split('.'), arrIndex = -1
props.reduce((o,d,i) => ( 
                         arrIndex = d.indexOf('[') > -1 && d[d.indexOf('[') + 1],
                          arrIndex && (d = d.slice(0, d.indexOf('['))),
                           i == props.length - 1 
                              ? o[d] = value 
                              : (o[d] = o[d] || {}, (arrIndex && (Array.isArray(o[d]) || (o[d] = [o[d]]))), arrIndex && o[d][arrIndex] || o[d])
                        )
                , obj)
}

updateValue(obj1, 'level1.level2.level3.title', 'abcd')
updateValue(obj2, 'level1.level2.level3.title', 'abcd')
updateValue(obj3, 'level1.level2[0].title', 'abcd')

console.log(obj1)
console.log(obj2)
console.log(obj3)

Turn nested object key paths into strings. help. UPDATE: Turned my solution into You would have to keep the list of keys within function and concat them to get  Object.keys () returns an array whose elements are strings corresponding to the enumerable properties found directly upon object. The ordering of the properties is the same as that given by looping over the properties of the object manually. // simple array const arr = ['a', 'b', 'c']; console.log (Object.keys (arr)); // console: ['0', '1', '2

This can be done by hand, indexing into the object structure repeatedly and creating new objects as necessary along the path to the destination key:

const updateField = (o, path, entry) => {
  path = path.split(".");
  let curr = o;
  
  while (path.length > 1) {
    const dir = path.shift();    
    const parent = curr;
    curr = curr[dir];

    if (undefined === curr) {
      parent[dir] = {};
      curr = parent[dir];
    }
  }
  
  if (path.length === 1) {
    curr[path.shift()] = entry;
  }
  
  return o;
};

var obj = {
  level1 : {
    level2: {
      level3: {
        title: "winner"
      }
    }
  }
};

console.log(JSON.stringify(updateField(obj, "level1.level2.level3.title", "super-winner"), null, 2));
console.log(JSON.stringify(updateField({}, "level1.level2.level3.title", "super-winner"), null, 2));

Property accessors provide access to an object's properties by using the dot notation or the bracket notation. The keys in this array are the names of the object's properties. It's typical In the SpiderMonkey JavaScript engine, this string would be " [object Object] ". Update compatibility data on GitHub  An object in JavaScript is a data type that is composed of a collection of names or keys and values, represented in name:value pairs. The name:value pairs can consist of properties that may contain any data type — including strings, numbers, and Booleans — as well as methods , which are functions contained within an object.

You can use .set function of lodash https://lodash.com/docs#set

ex: _.set(obj, 'level1.level2.level3.title', 'super-winner');

Or use ES6 syntax function:

var str = 'level1.level2.level3.title';
str.split('.').reduce((p, c, index) => {
    if (index === str.split('.').length - 1) {
        if (typeof p[c] !== "object") { // string, number, boolean, null, undefined
            p[c] = 'super-winner'
        }
        return p[c];
    } else {
        if (!p[c] || typeof p[c] !== 'object') {
            p[c] = {};
        }
        return p[c];
    }
}, obj)

console.log(obj);

An object initializer is a comma-delimited list of zero or more pairs of The values of these keys are a string "bar" , the number 42 , and another object. Once you have created an object, you might want to read or change  CRUD nested keys on JavaScript object. Utility for remapping key names of an object shallowly and depply nested too, that supports currying for partial

The deepObject function takes all of the keys of an object and iterates over them, First, we stringify the object, then parse the resulting string. like there might be a need to change a given object on a deeper level (nested objects/arrays). If it is we flatten it and then concat the value to the result array. This approach of looping through keys and values in an object can be used to perform more useful operations on the object, for instance the method could call a function passed in on each of the values. An example of this is in the foIn method in mout.js which iterates through the object keys and values calling the function passed in.

Change language: get_object_vars — Gets the properties of the given object That which seems to be spaces into array keys are '\0' characters, so the $​value = $obj->$prop; // now you have the property name and its value We ran into a problem using this function when we had a JS array nested inside a JS hash. This way, the next level key will always be accessed from an object that exists or an empty object, but never from undefined. Unfortunately, you cannot access nested arrays with this trick. Access Nested Objects Using Array Reduce. Array reduce method is very powerful and it can be used to safely access nested objects.

It is often used when we want to store list of elements and access them by a single variable. We can Method 1: In this method, we will use Object.keys() and map() to achieve this. Approach: By How to Convert JS Object to JSON String in JQuery/Javascript? How to How to change the ID of element using JavaScript ? In short, there are no limitations on property names. They can be any strings or symbols (a special type for identifiers, to be covered later). Other types are automatically converted to strings. For instance, a number 0 becomes a string "0" when used as a property key:

Comments
  • You will need to write a function to do that which splits the string on ., iterates over the array of keys and navigates into the object optionally creating empty objecs.
  • there are libraries that support that lodash.com/docs/4.17.10#get
  • Possible duplicate of Accessing nested JavaScript objects with string key
  • Is this possible making this work for level1.level2[0].title too? (notice the array inside object). BTW is reduce is ES6?
  • Why not? Just add the appropriate condition e.g. if (typeof acc[curr] === 'array') { acc[curr][0] = {title} } Stackoverflow is not for solving everything for you, it is to help you to solve things. So you really should comprehend the code I wrote line-by-line, understand what reduce method does and solve all the possible cases that are specific for your app (we cannot forsee all of them)
  • Is this possible making this work for level1.level2[0].title too? (notice the array inside object). BTW is this ES6?
  • Arrow functions ( => ) I used above was introduced in ES6. And regarding array indexes you mentioned, let me see to it.
  • As this array notation have many possibilities. I tried to cover whatever I could think of, you can have a look at it and see if this is what you are looking for. I have edited my answer above to cater this. Thanks.
  • Hey that does not work (it prints the first char of the string, not creating array instance inside the object
  • Then I would suggest you open a new question with new requirement. Please don't forget to show your attempt, this helps fellow users to see what you are missing in your attempt. All the best :)
  • This will not cover this case: "- sometimes I need to update an undefined object..."