Murakami
Murakami

Reputation: 3760

Change object keys from underscore format to camelCase format

I'm trying to get this:

  const obj = {
    keyFirst: 'firstVal',
    keySecond: 'secondVal',
  };

from this:

  const obj = {
    key_first: 'firstVal',
    key_second: 'secondVal',
  };

...so to change underscore key format to camelCase format.

I tried to achieve it by using reduce function:

  const renameKeys = obj => Object
    .keys(obj)
    .reduce((acc, key) => {
      const modifiedKey = key.replace(/_([a-z])/g, function f(g) {
        return g[1].toUpperCase();
      });
      return ({
        ...acc,
        ...{ [modifiedKey]: obj[key] },
      }, {});
    });

  console.log(renameKeys(obj));

But this won't work and return empty objects. How can I change it to achieve my goal?

Upvotes: 4

Views: 1301

Answers (2)

brk
brk

Reputation: 50291

You can split the key name by group and use $1 & $2 where these represent group

const obj = {
  keyFirst: 'firstVal',
  keySecond: 'secondVal',
};


let newObj = {}


for (let keys in obj) {
  newObj[keys.replace(/([a-z0-9])([A-Z])/g, '$1_$2').toLowerCase()] = obj[keys]

}

console.log(newObj)

Upvotes: 0

CertainPerformance
CertainPerformance

Reputation: 370679

The problem is

  return ({
    ...acc,
    ...{ [modifiedKey]: obj[key] },
  }, {});

You're unintentionally using the comma operator - although the new object is evaluated, the whole expression inside the parentheses evaluates to the final value in the comma-separated list, which is the empty object, which becomes the accumulator on the next iteration.

Don't use the comma operator in the return, and pass {} as a second argument to reduce instead:

  const obj = {
    key_first: 'firstVal',
    key_second: 'secondVal',
  };

  const renameKeys = obj => Object
    .keys(obj)
    .reduce((acc, key) => {
      const modifiedKey = key.replace(/_([a-z])/g, function f(g) {
        return g[1].toUpperCase();
      });
      return ({
        ...acc,
        ...{ [modifiedKey]: obj[key] },
      });
    }, {});

  console.log(renameKeys(obj));

Also, rather than using Object.keys, you might consider Object.entries instead, because [modifiedKey]: value is probably a bit clearer than [modifiedKey]: obj[key]:

const obj = {
  key_first: 'firstVal',
  key_second: 'secondVal',
};

const renameKeys = obj => Object
  .entries(obj)
  .reduce((acc, [key, val]) => {
    const modifiedKey = key.replace(/_([a-z])/g, g =>  g[1].toUpperCase());
    return ({
      ...acc,
      ...{ [modifiedKey]: val },
    });
  }, {});

console.log(renameKeys(obj));

Upvotes: 2

Related Questions