Skip to content

Instantly share code, notes, and snippets.

@tusharf5
Last active July 30, 2022 11:00
Show Gist options
  • Save tusharf5/6bdf37908f135d842e74d6e75b6e17b1 to your computer and use it in GitHub Desktop.
Save tusharf5/6bdf37908f135d842e74d6e75b6e17b1 to your computer and use it in GitHub Desktop.
Get nested value from an object using a key path. Supports keys with `dots` in the path.
function splitPath(path) {
const paths = [];
for (let i = 0; i < path.length; i++) {
const c = path[i];
if (c === ']') {
continue;
}
if (i === 0) {
let end = i + 1;
let char = path[end];
while (true) {
char = path[end];
if (char === '.' || char === '[') {
break;
}
end++;
}
paths.push(path.slice(i, end).replaceAll(/["']/g, ''));
i = end - 1;
continue;
}
if (c === '[') {
let end = i + 1;
let char = path[end];
while (true) {
char = path[end];
if (char === ']') {
break;
}
end++;
}
paths.push(path.slice(i + 1, end).replaceAll(/["']/g, ''));
i = end - 1;
continue;
}
if (c === '.') {
let end = i + 1;
let char = path[end];
let isEnd = end === path.length - 1;
while (true) {
char = path[end];
if (char === '.' || char === '[' || end === path.length - 1) {
break;
}
end++;
isEnd = end === path.length - 1;
}
if (i + 1 === end) {
paths.push(path.slice(i + 1, end + 1).replaceAll(/["']/g, ''));
} else if (isEnd) {
paths.push(path.slice(i + 1, end + 1).replaceAll(/["']/g, ''));
} else {
paths.push(path.slice(i + 1, end).replaceAll(/["']/g, ''));
}
i = end - 1;
continue;
}
}
return paths;
}
/**
* Supports
* a.b.c.0.abc['ss'].a[4].xyz['key.with.a.dot.in.its.name']['path'][23]
*/
function select(payload, keyPath) {
let ref = payload;
const keys = splitPath(keyPath);
for (const key of keys) {
ref = isNaN(key) ? ref[key] : ref[Number(key)];
}
return ref;
}
@tusharf5
Copy link
Author

Example

select({ a: { b: [ { c: [ { d: { 'v.b': 2 } } ] } ] }  }, "a.b.0.c.0.d['v.b']"); // 2

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment