Javascript: Get Deep Value from Object by Passing Path to It as String

Javascript: Get deep value from object by passing path to it as string

Consider this:

var obj = {
foo: { bar: 'baz' }
};

function deepFind(obj, path) {
var paths = path.split('.')
, current = obj
, i;

for (i = 0; i < paths.length; ++i) {
if (current[paths[i]] == undefined) {
return undefined;
} else {
current = current[paths[i]];
}
}
return current;
}

console.log(deepFind(obj, 'foo.bar'))

How to Get the Value of nested JavaScript object property by string key

You can use helper function to achieve this, e.g.:

var data = {
cont: {
model: {
Inspection: {
InspectionName: "Hello world"
}
}
}
};

function getNestedValue(obj, key) {
return key.split(".").reduce(function(result, key) {
return result[key]
}, obj);
}

console.log(getNestedValue(data, "cont.model.Inspection.InspectionName"));

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

option #1 (not recommended) - use the eval function:

var projects = {
a : {
b : {
c : 1
}
}
}
function get(myPath) {
debugger;
return eval("projects." + myPath)
}
console.log(get('a.b.c'))

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.

Set value in object by path and flatten again with objects and arrays

I have totally reworked the deepSet function now. It now supports multiple arrays and gaps in the arrays etc. I think this covers now every usecase. In the end it was way easier to figure the logic out when I started over without the reduce function

export const deepSet = (obj: any, path: string, val: any) => {
path = path.replaceAll("[", ".[");
const keys = path.split(".");

for (let i = 0; i < keys.length; i++) {
let currentKey = keys[i] as any;
let nextKey = keys[i + 1] as any;
if (currentKey.includes("[")) {
currentKey = parseInt(currentKey.substring(1, currentKey.length - 1));
}
if (nextKey && nextKey.includes("[")) {
nextKey = parseInt(nextKey.substring(1, nextKey.length - 1));
}

if (typeof nextKey !== "undefined") {
obj[currentKey] = obj[currentKey] ? obj[currentKey] : (isNaN(nextKey) ? {} : []);
} else {
obj[currentKey] = val;
}

obj = obj[currentKey];
}
};

How to store a object path

You could use an array for the keys and a function wich reduces the object by using the keys for the property access.

const getValue = (object, path) => path.reduce((r, k) => (r || {})[k], object);
var object = { india: { chennai: { sholing: "hi" } } }, path = ['india', 'chennai', 'sholing'];
console.log(object.india.chennai );console.log(getValue(object, path));

Getting a value from a JSON object by its path

You could reduce the object with the splitted path values.

var object = { result: { data: { point1: "x", value: 2 }, foo: { bar: 7 } } },    path = 'result.data.value',    getValue = (o, p) => p.split('.').reduce((r, k) => r[k], o);
console.log(getValue(object, path));

Find a full object path to a given value with JavaScript

Use a recursive function to look for the item you want. Once the function find it, it will return an array. Each step back of the recursion will unshift the object key of this step:

function find(obj, item) {
for(var key in obj) { // for each key in obj (obj is either an object or an array)
if(obj[key] && typeof obj[key] === "object") { // if the current property (value of obj[key]) is also an object/array
var result = find(obj[key], item); // try finding item in that object
if(result) { // if we find it
result.unshift(key); // we shift the current key to the path array (result will be an array of keys)
return result; // and we return it to our caller
}
} else if(obj[key] === item) { // otherwise (if obj[key] is not an object or array) we check if it is the item we're looking for
return [key]; // if it is then we return the path array (this is where the path array get constructed)
}
}
}

The output of this function will be an array of keys leading to item. You can easily transform it to the format in the question:

function findFormatted(obj, item) {
var path = find(obj, item); // first let's get the path array to item (if it exists)
if(path == null) { // if it doesn't exist
return ""; // return something to signal its inexistance
}
return 'myObj["' + path.join('"]["') + '"]'; // otherwise format the path array into a string and return it
}

Example:

function find(obj, item) {    for(var key in obj) {        if(obj[key] && typeof obj[key] === "object") {            var result = find(obj[key], item);            if(result) {                result.unshift(key);                return result;            }        } else if(obj[key] === item) {            return [key];        }    }}
function findFormatted(obj, item) { var path = find(obj, item); if(path == null) { return ""; } return 'myObj["' + path.join('"]["') + '"]';}
var myObj = [{"name":"group1","children":[{"name":"group2","children":[{"name":"item0"}]}]},{"name":"item1"},{"name":"needleGroup","children":[{"name":"needleNestedGroup","children":[{"name":"item3"},{"name":"needleNestedDeeperGroup","children":[{"name":"needle"}]}]}]}];
console.log("find(myObj, \"needle\"): " + JSON.stringify(find(myObj, "needle")));console.log("findFormatted(myObj, \"needle\"): " + findFormatted(myObj, "needle"));


Related Topics



Leave a reply



Submit