javascriptreactjswebfrontend

Javascript - Change name of all object keys in nested arrays


This is the array i get:

const packages = [
  {
    id: '641a1690-6c8b-4ada-ae97-8d82cc4fe7a3',
    name: 'com.sample',
    children: {
      id: 'd7384f60-e4ab-4a86-8e2e-0f66cc32f',
      name: 'child.computer.com',
      children: { id: 'e4ab-4a86-0f66cc32f560', name: 'child.com' }
    }
  },
  { id: 'd7384f60-e4ab-4a86-8e2e-0f66cc32f560', name: 'computer.com' },
  { id: 'ca7f972e-64ee-4cb0-80b9-1036fac69d32', name: 'java.util' }
];

So, it is an array of objects, and each object can have children, which again have id, name and possibly children (children is optional), and so on, it can be nested X times. I want to change key names, id to key, name to title and children will remain children. So, my problem is that i don't know how to change keys inside children, i just change the first level and that is all.. It should be like:

{
    key: '641a1690-6c8b-4ada-ae97-8d82cc4fe7a3',
    title: 'com.sample',
    children: {
      key: 'd7384f60-e4ab-4a86-8e2e-0f66cc32f',
      title: 'child.computer.com',
      children: { key: 'e4ab-4a86-0f66cc32f560', title: 'child.com' }
    }   
}

Solution

  • You can do this by using Recursion.

    Check if the value of the [key-value] pair from the Object#entries() call is an object.

    If so, call the transformObj function again recursively for that value. Else return the value as is.

    And finally convert the array of [key-value] pairs back to an object by using Object#fromEntries:

    const packages = [{ id: '641a1690-6c8b-4ada-ae97-8d82cc4fe7a3', name: 'com.sample', children: { id: 'd7384f60-e4ab-4a86-8e2e-0f66cc32f', name: 'child.computer.com', children: { id: 'e4ab-4a86-0f66cc32f560', name: 'child.com' }}}, { id: 'd7384f60-e4ab-4a86-8e2e-0f66cc32f560', name: 'computer.com' }, { id: 'ca7f972e-64ee-4cb0-80b9-1036fac69d32', name: 'java.util' }];
    const replacer = { "id": "key", "name" :"title"};
    const transformObj = (obj) => {
      if(obj && Object.getPrototypeOf(obj) === Object.prototype){
        return Object.fromEntries(
        Object.entries(obj)
              .map(([k, v]) => [replacer[k] || k, transformObj(v)])
        );
      }
      //Base case, if not an Object literal return value as is
      return obj;
    }
    console.log(packages.map(o => transformObj(o)));