admin管理员组

文章数量:1405131

How to recursively convert object keys from snake case to camel case using plain javascript without relying on external libraries such as Lodash. Below is an attempt that only works for first level of the object. What's the best way to do this?

const obj = {
  key_first: 'firstVal',
  key_second: 'secondVal',
  key_third: null,
  nested_obj: {
    nested_one: 'nested 1 value',
    nested_two: 'nested 2 value'
  },
  nested_arr: [{
    nested_obj_one: 'nested obj val 1'
  }, {
    nested_obj_two: 'nested obj val 2'
  }, {
    level_3_nested: [{
      level_3_key: 'level 3 value',
      level_3_another_key: 'another level 3 value'
    }]
  }]
};
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));

Update: Added key with value of null.

How to recursively convert object keys from snake case to camel case using plain javascript without relying on external libraries such as Lodash. Below is an attempt that only works for first level of the object. What's the best way to do this?

const obj = {
  key_first: 'firstVal',
  key_second: 'secondVal',
  key_third: null,
  nested_obj: {
    nested_one: 'nested 1 value',
    nested_two: 'nested 2 value'
  },
  nested_arr: [{
    nested_obj_one: 'nested obj val 1'
  }, {
    nested_obj_two: 'nested obj val 2'
  }, {
    level_3_nested: [{
      level_3_key: 'level 3 value',
      level_3_another_key: 'another level 3 value'
    }]
  }]
};
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));

Update: Added key with value of null.

Share Improve this question edited Oct 6, 2019 at 15:02 Steve asked Oct 6, 2019 at 12:58 SteveSteve 5,19414 gold badges51 silver badges65 bronze badges 1
  • Hi, Try this stackoverflow./a/73220750/11888809 , you can do this in one line of code – SWIK Commented Aug 3, 2022 at 11:22
Add a ment  | 

4 Answers 4

Reset to default 4

I'd .map the Object.entries, replacing the key in the entry, while recursively calling renamekeys on the value, and pass the whole array entry to Object.fromEntries to turn it back into an object.

Since you have nested arrays too, not just nested objects. you'll have to test for them and .map each item via renameKeys if found.

You also probably want to tweak the regex so that all underscores get replaced, not just those followed by alphabetical characters:

const obj = {
  key_first: 'firstVal',
  key_second: 'secondVal',
  nested_obj: {
    nested_one: 'nested 1 value',
    nested_two: 'nested 2 value'
  },
  nested_arr: [{
    nested_obj_one: 'nested obj val 1'
  }, {
    nested_obj_two: 'nested obj val 2'
  }, {
    level_3_nested: [{
      level_3_key: 'level 3 value',
      level_3_another_key: 'another level 3 value'
    }]
  }]
};

const processVal = val => (
  typeof val !== 'object'
  ? val
  : Array.isArray(val)
    ? val.map(renameKeys)
    : renameKeys(val)
);
const renameKeys = obj => Object.fromEntries(
  Object.entries(obj)
    .map(([key, val]) => [
      key.replace(/_(.)/g, g =>  g[1].toUpperCase()),
      processVal(val)
    ])
);
console.log(renameKeys(obj));

To permit null values as well:

const obj = {
  key_first: 'firstVal',
  key_second: 'secondVal',
  nested_obj: {
    nested_one: 'nested 1 value',
    nested_two: 'nested 2 value'
  },
  nested_arr: [{
    nested_obj_one: 'nested obj val 1'
  }, {
    nested_obj_two: 'nested obj val 2'
  }, {
    level_3_nested: [{
      level_3_key: 'level 3 value',
      level_3_another_key: 'another level 3 value'
    }]
  }]
};

const processVal = val => (
  (typeof val !== 'object' || val === null)
  ? val
  : Array.isArray(val)
    ? val.map(renameKeys)
    : renameKeys(val)
);
const renameKeys = obj => Object.fromEntries(
  Object.entries(obj)
    .map(([key, val]) => [
      key.replace(/_(.)/g, g =>  g[1].toUpperCase()),
      processVal(val)
    ])
);
console.log(renameKeys(obj));

If the arrays can be on the first level, then use val.map(processVal) in processVal, and first call processVal instead of renameKeys:

const obj = {
  simple_arr: ['a1', 'b1', 'c1'],
  key_first: 'firstVal',
  key_second: 'secondVal',
  nested_obj: {
    nested_one: 'nested 1 value',
    nested_two: 'nested 2 value'
  },
  nested_arr: [{
    nested_obj_one: 'nested obj val 1'
  }, {
    nested_obj_two: 'nested obj val 2'
  }, {
    level_3_nested: [{
      level_3_key: 'level 3 value',
      level_3_another_key: 'another level 3 value'
    }]
  }]
};

const processVal = val => (
  (typeof val !== 'object' || val === null)
  ? val
  : Array.isArray(val)
    ? val.map(processVal)
    : renameKeys(val)
);
const renameKeys = obj => Object.fromEntries(
  Object.entries(obj)
    .map(([key, val]) => [
      key.replace(/_(.)/g, g =>  g[1].toUpperCase()),
      processVal(val)
    ])
);
console.log(processVal(obj));

Add recursive call for nested object

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

You can use for..in something like this

const obj = {key_first: 'firstVal',key_second: 'secondVal',nested_obj: {nested_one: 'nested 1 value',nested_two: 'nested 2 value'},nested_arr: [{nested_obj_one: 'nested obj val 1'}, {nested_obj_two: 'nested obj val 2'}, {level_3_nested: [{level_3_key: 'level 3 value',level_3_another_key: 'another level 3 value'}]}]};

let keyChanger = (obj) => {
  for (let key in obj) {
    if (typeof obj[key] === 'object') {
      if (Array.isArray(obj[key])) {
        obj[key].map(v => keyChanger(v))
      } else {
        keyChanger(obj[key])
      }
    }
    const modifiedKey = key.replace(/_([a-z])/g, g => g[1].toUpperCase());
    obj[modifiedKey] = obj[key]
    delete obj[key]
  }
  return obj
}

console.log(keyChanger(obj))

I think this method of camelizing nested object keys will save lot of iterations.

const camelizeNestedKeys = function(dataObj) {
    return JSON.parse(JSON.stringify(dataObj).trim().replace(/("\w+":)/g, function(keys) {
        return keys.replace(/(.(\_|-|\s)+.)/g, function(subStr) {
            return subStr[0]+(subStr[subStr.length-1].toUpperCase());
        })
    }));
}


const data = {
    'id':'123',
    'employee_name': 'John',
    'employee_type': 'new'  
};

const nestedData = {
    'id':'123',
    'employee_name': 'John',
    'employee_type': 'new',
    'exployee_projects': [
        {"project_name": "test1", "project_year": 2004},
        {"project_name": "test2", "project_year": 2004}
    ]
};

console.log(camelizeNestedKeys(data));

console.log(camelizeNestedKeys(nestedData));

本文标签: javascriptRename Object Keys from Snake Case to Camel Case Recursively Without Using LodashStack Overflow