dzm
dzm

Reputation: 23544

Javascript convert object with array string keys to key/name value's

I have an object with named keys like this

{ 
 'name[first]': 'john',
 'name[last]': 'doe'
 }

that I want to convert to:

{ 
 'name' : {
     'first' : 'john',
     'last' : 'doe'
   }
 }

Any idea on an elegent way to do this?

Upvotes: 1

Views: 169

Answers (5)

Legends
Legends

Reputation: 22682

You can try the following:

var obj = {
  'name[first]': 'john',
  'name[last]': 'doe'
}

var result = Object.keys(obj).reduce(function(newObj, prop) { 
  var key = prop.split(/\[|\]/)[1];  
  newObj[key] = obj[prop];
  return newObj;
}, {})
  
console.log(result);

Upvotes: 0

Nenad Vracar
Nenad Vracar

Reputation: 122047

You can use reduce() to return obj and regular expression to split key.

var obj = {
  'name[first]': 'john',
  'name[last]': 'doe'
}

var result = Object.keys(obj).reduce(function(r, e) {
  var key = e.split(/\[(.*?)\]/)
  if (!r[key[0]]) r[key[0]] = {}
  r[key[0]][key[1]] = obj[e]
  return r;
}, {})

console.log(result)

For nested key structure you could again use reduce but with different approach to keys but then you face problem of deep merge of object and for that you can use lodash.

var obj = {
  'name[first[foo]]': 'john',
  'name[last]': 'doe',
  'name[last[foo[bar]]]': 'doe'
}

var result = Object.keys(obj).reduce(function(r, e) {
  var key = e.replace(/\[/g, '.').replace(/\]/g, '').split('.')
  var o = {}

  key.reduce(function(re, el, i) {
    return i != key.length - 1 ? re[el] = {} : re[el] = obj[e]
  }, o)

  r = _.merge(r, o)
  return r;
}, {})

console.log(JSON.stringify(result, 0, 4))
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.15.0/lodash.min.js"></script>

Upvotes: 4

Vladu Ionut
Vladu Ionut

Reputation: 8193

var obj = {
  'name[first]': 'john',
  'name[last]': 'doe'
}
var newObj = {};
for (var property in obj) {
  if (obj.hasOwnProperty(property)) {
    var keys = property.match(/(\w+)/g);
    if (keys && keys.length == 2) {
      newObj[keys[0]] = newObj[keys[0]] || {};
      newObj[keys[0]][keys[1]] = obj[property];
    }



  }
}
console.log(newObj);

Upvotes: 0

RomanPerekhrest
RomanPerekhrest

Reputation: 92854

The solution using Object.keys, Array.prototytpe.reduce and String.prototype.match functions:

var obj = {'name[first]': 'john', 'name[last]': 'doe'};

var result = Object.keys(obj).reduce(function (o, key) {
  var parts = key.match(/^(\w+)\[(\w+)\]$/);
  if (!o[parts[1]]) {
    o[parts[1]] = {};            
  }
  o[parts[1]][parts[2]] = obj[key];
  return o;        
}, {});

console.log(result);

Upvotes: 0

J. Titus
J. Titus

Reputation: 9690

Using a for..in loop and constructing a new object:

var obj = {
    'name[first]': 'john',
    'name[last]': 'doe'
};

var newObj = {}
for (var key in obj) {
    var parts = key.split(/\[|\]/);
    if(!newObj.hasOwnProperty(parts[0]))
      newObj[parts[0]] = {};
    newObj[parts[0]][parts[1]] = obj[key];
}

console.log(newObj);

Upvotes: 1

Related Questions