3

I have a javascript object defined as (which created elsewhere that I have no control over).

var config = {
    a: 2
}

config['b[1]'] = 9;
config['b[2]'] = 8;
config['c[test]'] = 3;

I would like to convert it to something like. ( for key 1, I mean config['b']['1'] = 9 )

var transformed = {
    a: 2,
    b: { 1: 9, 2: 8},
    c: { test: 3}
}

How do I do that easily? I use lodash if it helps.

jay.m
  • 1,618
  • 3
  • 16
  • 28

3 Answers3

4

You can use a for() loop to go through objects keys and use match function to obtain the necessary new keys. Hope this helps

var config = {
  a: 2
};

config['b[1]'] = 9;
config['c[test]'] = 3;

var key, match, obj;

for(key in config) {
  match = key.match(/(.+)\[(.+)\]/);
  if(match) { // for example key is 'b[1]'
    obj = config[match[1]] || {}; // <= Update create new object or use filled
    obj[match[2]] = config[key]; // add new property (match[2] => '1') to new object
    config[match[1]] = obj; // add new property (match[1] => 'b') to config
    delete config[key]; // remove composite key
  }
}
console.dir(config);
yurzui
  • 205,937
  • 32
  • 433
  • 399
  • Maybe some explanation along with the code would be useful. – Anton Sarov Jan 08 '16 at 19:36
  • I think there's a bug in this code, if add `config['b[2]'] = 8` to it. It will NOT be transformed. My fault, since I didn't add multiple b elements in the question. – jay.m Jan 08 '16 at 20:46
1

JS has no built-in functionality to do that.
But u can use a little helper-method.

function setProp(obj, prop, value){
    var s = String(prop), 
        a = s.replace("[", "][").split("]["),
        last = a.length - 1,
        p, q;

    if(last && s.substr(-1) === "]"){
        p = a[last];
        a[last] = p.substr(0, p.length-1);
    }

    for(var i=0, me = obj; i<last; ++i){
        var p = a[i];

        //check if property is not a primiive or undefined
        var hasProp = p in me && me[p] === Object(me[p]);
        if(!hasProp){ //create a object for it
            q = a[i+1];
            //use an Array for numeric indices
            me[p] = (q === (+q).toString())? []: {};

            //always use Objects
            //me[p] = {};
        }
        me = me[p];
    }

    me[a[last]] = value;
}

var config = { a: 2 };

setProp(config, 'b[1]', 9);
setProp(config, 'b[2]', 8);
setProp(config, 'c[test]', 3);

Be careful with your strings, the parser is pretty basic It assumes the input string to be valid.

Thomas
  • 3,513
  • 1
  • 13
  • 10
0

Not sure how performant this is compared to eval, but it should work for most cases

var obj = {
    some: {
        string: {
            location: 2
        }
    }
};

console.log(getDataFromObj(obj, "some.string['location']"));

function getDataFromObj (obj, key) {
    return new Function("return obj." + key)()
}
neaumusic
  • 10,027
  • 9
  • 55
  • 83