Created
October 2, 2019 21:30
-
-
Save rauljose/e03e582008ffb9c667003c92bde77522 to your computer and use it in GitHub Desktop.
Utilities for objects. Find key(s) within sub-objects, recursively. get/set deep keys by path
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Utilities for object {} | |
* | |
* @usage | |
* iaObjectUtil.findKeyFirst('b', {a:1,b:2,c:{a:'ac', b:'bc'}}) | |
* => [{ path: "b", value: 2 }] // key not found returns [] | |
* | |
* iaObjectUtil.findKeyAll('b', {a:1,b:2,c:{a:'ac', b:'bc'}}) | |
* => [{ path: "b", value: 2 },{ path: "c.b", value: "bc" }] // not found [] | |
* | |
* iaObjectUtil.getPath('c.b',{a:1,b:2,c:{a:'ac', b:'bc'}}) | |
* => 'bc' // not found throws error Key not found: key | |
* iaObjectUtil.getPath('c/b',{a:1,b:2,c:{a:'ac', b:'bc'}}, '/') | |
* => 'bc' // change path separator from default to / | |
* | |
* iaObjectUtil.setPath('c.d', 33, {a:1,b:2} ) | |
* => {a:1,b:2, c:{d:33}} | |
* | |
* @author Raúl José Santos | |
* @author Informática Asociada | |
* @copyright 2019 | |
* @license MIT | |
* @version 1.0.0 | |
*/ | |
var iaObjectUtil = { | |
/** | |
* Find first key in an object, searching within object's objects | |
* | |
* @param key string | |
* @param obj object | |
* @return array of objects, empty array on not found | |
* @example | |
* findKeyFirst('b', {a:1,b:2,c:{a:'ac', b:'bc'}}) | |
* => [{ path: "b", value: 2 }] // key not found returns [] | |
*/ | |
findKeyFirst: function(key, obj) { | |
var found = [], visited = {}; | |
/** | |
* | |
* @param searchKey string | |
* @param onObj object | |
* @param p string | |
* @private | |
*/ | |
function _findFirstKey(searchKey, onObj, p) { | |
if(typeof onObj !== 'object' || onObj === null) | |
return; | |
if(onObj.hasOwnProperty(searchKey)) { | |
var f = (p + '.' + searchKey).substr(1); | |
found[found.length] = {path:f, value:onObj[searchKey]}; | |
visited[f]=true; | |
return; | |
} | |
for(var c in onObj) | |
if(onObj.hasOwnProperty(c) && typeof onObj[c] === 'object') { | |
var f1 = p + '.' + c; | |
if(!visited.hasOwnProperty(f1)) { | |
visited[f1]=true; | |
_findFirstKey(searchKey, onObj[c],f1); | |
} | |
} | |
} | |
_findFirstKey(key, obj, ''); | |
return found; | |
}, | |
/** | |
* Find all key in object, searching within object's objects | |
* | |
* @param key string | |
* @param obj object {} | |
* @return array of objects, empty array on not found | |
* @example | |
* findKeyAll('b', {a:1,b:2,c:{a:'ac', b:'bc'}}) | |
* => [{ path: "b", value: 2 },{ path: "c.b", value: "bc" }] // key not found returns [] | |
*/ | |
findKeyAll: function(key, obj) { | |
var found = [], visited = {}; | |
function _findKeyAll(key, obj, p) { | |
if(typeof obj !== 'object' || obj === null) | |
return; | |
if(obj.hasOwnProperty(key)) { | |
found[found.length] = {path:(p + '.' + key).substr(1), value:obj[key]}; | |
visited[p]=true; | |
} | |
for(var c in obj) | |
if(obj.hasOwnProperty(c) && typeof obj[c] === 'object' ) { | |
var f = p + '.' + c; | |
if(!visited.hasOwnProperty(f)) { | |
_findKeyAll(key, obj[c], f); | |
visited[f]=true; | |
} | |
} | |
} | |
_findKeyAll(key, obj, ''); | |
return found; | |
}, | |
/** | |
* Returns the value of an object's property with path keys | |
* | |
* @param path string the keys sperated by pathSeparator | |
* @param obj object {} | |
* @param pathSeparator string string to separate keys, default . | |
* @return mixed value at path or trhows error: Key not found: key | |
* | |
* @example | |
* getPath('c.b',{a:1,b:2,c:{a:'ac', b:'bc'}}) | |
* => 'bc' // not found throws error | |
* getPath('c/b',{a:1,b:2,c:{a:'ac', b:'bc'}}, '/') | |
* => 'bc' // change path separator from default to / | |
*/ | |
getPath: function(path, obj, pathSeparator) { | |
var o=obj, keys = path.split(typeof pathSeparator === 'undefined' ? '.' : pathSeparator), i=0; | |
for(var len=keys.length; i<len; ++i) | |
if(o.hasOwnProperty(keys[i])) | |
o = o[keys[i]]; | |
else | |
throw "Key not found!: " + keys[i]; | |
return o; | |
}, | |
/** | |
* for path keys set the value, creating non existing keys, or replacing | |
* | |
* | |
* @param path string the keys sperated by pathSeparator | |
* @param value mixed the value to set to the last key in path | |
* @param obj object {} | |
* @param pathSeparator string string to separate keys, default . | |
* @return object the modified object obj with the new value | |
* | |
* @example | |
* setPath('c.d', 33, {a:1,b:2} ) | |
* => {a:1,b:2, c:{d:33}} | |
*/ | |
setPath: function(path, value, obj, pathSeparator) { | |
var o=obj, keys = path.split(typeof pathSeparator === 'undefined' ? '.' : pathSeparator), i=0; | |
for(var len=keys.length-1; i<len; ++i) { | |
if(!o.hasOwnProperty(keys[i])) | |
o[keys[i]] = {}; | |
o = o[keys[i]]; | |
} | |
o[keys[i]] = value; | |
return obj; | |
}, | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment