[FIXED] What's the best way to turn all the keys of an nested array of objects to a camel case?

Issue

I want to turn all the keys of my array of objects to a camelCase in Typescript. I have the following data:

[
    {
       "Name":"Custom property",
       "Details":{
          "Address":"Huston",
          "Price":"1000000",
       },
       "Contact":{
          "Global":"3432432",
          "Local":"432423423"
       },
    },
    {
       "Name":"Myproperty",
       "Details":{
          "Address":"Huston",
          "Price":"10000001",
       },
       "Contact":{
          "Global":"34324323",
          "Local":"4324234233"
       },
    },
]

I have tried the below code, but it returns a new dictionary only with the details. How can I resolve that?

const newObjOptions = options.map((obj: any) =>
    Object.fromEntries(
      Object.entries(obj).map(([k, v]) => [_.camelCase(k), v])
    )
  );
  const newObjDetailsOptions = newObjOptions.map((obj: any) =>
    Object.fromEntries(
      Object.entries(obj.details).map(([k, v]) => [_.camelCase(k), v])
    )
  );

Solution

Your implementation works, if you log both newObjOptions and newObjDetailsOptions you’ll see that the top-layer of keys is indeed camel cased.

The main issue is that your code is not checking if the object contains any other objects.

const newObjOptions = options.map((obj) =>
  Object.fromEntries(
    // Here you should check if `v` is an object
    // and if so you need to camel-case that too
    Object.entries(obj).map(([k, v]) => [_.camelCase(k), v])
  )
)

To modify your code to do that you could do something like this:

// Here we check if `v` is an object and if it is we apply camel casing to that too
const camelCaseEntry = ([k, v]) => [_.camelCase(k), typeof v === 'object' ? camelCaseObject(v) : v]

const camelCaseObject = obj => Object.fromEntries(
  Object.entries(obj).map(camelCaseEntry)
)

const newObjOptions = options.map(camelCaseObject)
console.log(newObjOptions)

And that works with your example, but it breaks if your object contains an array (try it). This can be solved quite nicely with a simple recursive function, here’s an idea of what that might look like:

/**
 * Takes any object and returns a new object with all keys in camel case
 */
function camelCaseObject (object) {
  if (Array.isArray(object)) {
    return object.map(camelCaseObject)
  }
  if (typeof object === 'object') {
    const entries = Object.entries(object)
    return Object.fromEntries(entries.map(transfromEntry))
  }
  return object

  function transfromEntry ([k, v]) {
    return [
      _.camelCase(k),
      typeof v === 'object' ? camelCaseObject(v) : v
    ]
  }
}

Answered By – kil

Answer Checked By – Candace Johnson (Easybugfix Volunteer)

Leave a Reply

(*) Required, Your email will not be published