Accessing Nested JavaScript Objects and Arrays by String Path

Accessing nested JavaScript objects and arrays by string path

I just made this based on some similar code I already had, it appears to work:

Object.byString = function(o, s) {
s = s.replace(/\[(\w+)\]/g, '.$1'); // convert indexes to properties
s = s.replace(/^\./, ''); // strip a leading dot
var a = s.split('.');
for (var i = 0, n = a.length; i < n; ++i) {
var k = a[i];
if (k in o) {
o = o[k];
} else {
return;
}
}
return o;
}

Usage::

Object.byString(someObj, 'part3[0].name');

See a working demo at http://jsfiddle.net/alnitak/hEsys/

EDIT some have noticed that this code will throw an error if passed a string where the left-most indexes don't correspond to a correctly nested entry within the object. This is a valid concern, but IMHO best addressed with a try / catch block when calling, rather than having this function silently return undefined for an invalid index.

Access a nested property with a string

You'll have to split the string by the period, and then access each node iteratively. This could be done in a simple reduce:

var value = str.split('.').reduce(function(p,prop) { return p[prop] }, person);

The above would work regardless if str contains a period or not, i.e. for name as well as contact.phone.

Set state value using string path key from deeply nested object

You can use the solution in here dynamically-set-property-of-nested-object in your handleChange method like this:

// set method copied from the above link
function set(obj, path, value) {
var schema = obj;
var pList = path.split('.');
var len = pList.length;
for(var i = 0; i < len-1; i++) {
var elem = pList[i];
if( !schema[elem] ) schema[elem] = {}
schema = schema[elem];
}
schema[pList[len-1]] = value;
}
...

const handleChange = (prop) => (e) => {
let value;
if (typeof e.target.value === "number") {
value = parseInt(e.target.value);
}

if (typeof e.target.value === "string") {
value = e.target.value;
}

setPayload((prevState) => {
const newState = {...prevState};
set(newState, prop, value);
return newState;
})
};
....

onChange={handleChange("downloadConfiguration.product.initialDownloadLength")}

Is there an easy way to use nested object > array key in string form?

You can use Lodash#get:

let someObject = {
nonProblematicValue: "all good",
arrayOfValues: ["can't touch this"]
}

let keyThatDoesNotWork = "arrayOfValues[0]"
console.log(_.get(someObject, keyThatDoesNotWork))
<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.21/lodash.min.js"></script>

Accessing nested JavaScript objects and arrays by string path

I just made this based on some similar code I already had, it appears to work:

Object.byString = function(o, s) {
s = s.replace(/\[(\w+)\]/g, '.$1'); // convert indexes to properties
s = s.replace(/^\./, ''); // strip a leading dot
var a = s.split('.');
for (var i = 0, n = a.length; i < n; ++i) {
var k = a[i];
if (k in o) {
o = o[k];
} else {
return;
}
}
return o;
}

Usage::

Object.byString(someObj, 'part3[0].name');

See a working demo at http://jsfiddle.net/alnitak/hEsys/

EDIT some have noticed that this code will throw an error if passed a string where the left-most indexes don't correspond to a correctly nested entry within the object. This is a valid concern, but IMHO best addressed with a try / catch block when calling, rather than having this function silently return undefined for an invalid index.

How to access a nested object with string paths?

Yes, but not with the syntax you've proposed. This is easiest done when your path is an array of strings:

const tableData = (  { profile: { firstname: 'jim', lastname: 'johnson' }  })                                                                    const path = [ 'profile', 'firstname' ]
const valueAtPath = path.reduce((_, x) => _[x], tableData)
console.info(valueAtPath)

Access nested object dynamically by using array of string as a path

A simple approach would be to iterate the keyArray and also keep traversing the object with keys from keyArray

function getNestedObject( keyArr ){
var tmp = parent; //assuming function has access to parent object here
keyArr.forEach( function(key){
tmp = tmp[key];
});
return tmp;
}

Demo