I think this is an important question and I needed a variant, that allows for arrays nested in the objects AND for deep creation of non-existant fields.
I know you specified 'object' but in reality an object can also hold arrays.
In this situation the otherwise excellent code by @Marshall didn't help me out.
So I started fiddling and got the following code (hope this helps anyone):
function objGet(obj, keyString) {
// allow for arrays, returns undefined for non-existant-fields.
var keys=[{label:"",type:"field",is_array:false}], current_key=0;
for(var i=0;i<keyString.length;i++)
{
var c=keyString.charAt(i);
switch(c)
{
case ".":
current_key++;
keys[current_key]={label:"",type:"field",is_array:false};
break;
case "[":
keys[current_key].is_array=true;
current_key++;
keys[current_key]={label:"",type:"index",is_array:false};
break;
case "]":
break;
default:
keys[current_key].label+=c;
}
}
var part=obj;
for(i = 0; i < keys.length; i++)
{
var label=keys[i].label;
if(i==keys.length-1)
{
return part[label];
}else{
if(part[label] === undefined)
{
return undefined;
}
part = part[label];
}
}
}
function objSet(obj, keyString, val) {
// allows for arrays, deep creates non-existant fields.
var keys=[{label:"",type:"field",is_array:false}], current_key=0;
for(var i=0;i<keyString.length;i++)
{
var c=keyString.charAt(i);
switch(c)
{
case ".":
current_key++;
keys[current_key]={label:"",type:"field",is_array:false};
break;
case "[":
keys[current_key].is_array=true;
current_key++;
keys[current_key]={label:"",type:"index",is_array:false};
break;
case "]":
break;
default:
keys[current_key].label+=c;
}
}
var part=obj;
for(i = 0; i < keys.length; i++)
{
var label=keys[i].label;
if(i==keys.length-1)
{
part[label] = val;
}else{
if(part[label] === undefined)
{
// we need to create it for deep set!
if(keys[i].is_array)
{
part[label]=[];
}else{
part[label]={};
}
}
part = part[label];
}
}
}
// TESTS
var obj = {
test: 12,
high: {
sky: {
val: 14
}
},
kneedeep: [
{something:"som0",something_else:"elze0"},
{something:"som1",something_else:"elze1"}
],
low: [1, 2, 3]
};
var obj_str=JSON.stringify(obj);
console.log("testing with object: "+obj_str);
// TEST GET
console.log("test: "+objGet(obj, 'test')); // returns 999
console.log("high.sky.non.existant: "+objGet(obj, 'high.sky.non.existant')); // returns undefined
console.log("kneedeep[0].something: "+objGet(obj, 'kneedeep[0].something')); // returns "som0"
console.log("kneedeep[1].something_else: "+objGet(obj, 'kneedeep[1].something_else')); // returns "elze1"
console.log("high.sky.val: "+objGet(obj, 'high.sky.val')); // returns 14
console.log("low[0]: "+objGet(obj, 'low[0]')); // returns 1
// TEST SET
objSet(obj, 'test', 999); // return 999
console.log("result SET 'test', 999:");
console.log(JSON.stringify(obj));
obj=JSON.parse(obj_str); // reset the object
objSet(obj, 'high.sky.non.existant', 1234); // creates the necessary objects.
console.log("result SET 'high.sky.non.existant', 1234:");
console.log(JSON.stringify(obj));
obj=JSON.parse(obj_str); // reset the object
objSet(obj, 'high.sky.val', 111);
console.log("result SET 'high.sky.val', 111:");
console.log(JSON.stringify(obj));
obj=JSON.parse(obj_str); // reset the object
objSet(obj, 'kneedeep[0].something', 111);
console.log("result SET 'kneedeep[0].something', 111:");
console.log(JSON.stringify(obj));
obj=JSON.parse(obj_str); // reset the object
objSet(obj, 'kneedeep[1].something_else', 1234);
console.log("result SET 'kneedeep[1].something_else', 1234:");
console.log(JSON.stringify(obj));