Updating the names of keys within an object that includes nested child objects

I am looking to update the keys in an object that contains nested objects with similar structures.

Initially, my object looks like this:

objs = {
   "one":{
      "title":"bla",
      "amount":5,
      "children":[
         {
            "title":"bla",
            "identifier":"some text"
         },
         {
            "title":"bla2",
            "identifier":"some text2"
         }
      ]
   },
   "two":{
      "title":"bla",
      "amount":5,
      "children":[
         {
            "title":"bla",
            "identifier":"some text"
         },
         {
            "title":"bla2",
            "identifier":"some text2"
         }
      ]
   }
}

and I want to transform it into this:

objs = {
   "one":{
      "text":"bla",
      "amount":5,
      "items":[
         {
            "text":"bla",
            "identifier":"some text"
         },
         {
            "text":"bla2",
            "identifier":"some text2"
         }
      ]
   },
   "two":{
      "text":"bla",
      "amount":5,
      "items":[
         {
            "text":"bla",
            "identifier":"some text"
         },
         {
            "text":"bla2",
            "identifier":"some text2"
         }
      ]
   }
}

My goal is to rename every key children to items and every key title to text, regardless of how deeply nested the objects are. I have attempted using

spread & Destructuring Assignment
in forEach loops, but encountered challenges.

Answer №1

Here is a potential solution:

var objects = {
   "one":{
      "title":"example",
      "quantity":5,
      "children":[
         {
            "title":"example",
            "identifier":"some text"
         },
         {
            "title":"example2",
            "identifier":"some text2"
         }
      ]
   },
   "two":{
      "title":"example",
      "quantity":5,
      "children":[
         {
            "title":"example",
            "identifier":"some text"
         },
         {
            "title":"example2",
            "identifier":"some text2"
         }
      ]
   }
};



function transformObject(_object){
var output = [];
for(var key in _object){
var newObject = {};
for(var property in _object[key]){
  if(property == 'children'){
            newObject['items'] = transformObject(_object[key][property]);
  }else if(property == 'title'){
             newObject['text'] = _object[key][property];
  }else{
  newObject[property] = _object[key][property];
  }

        }
        output.push(newObject);
}
return output;
}

console.log(transformObject(objects));

Answer №2

To change the name, you can't simply rename it but you can assign a new value in the following way:

Object.keys(objects)
    .filter(k => objects[k].children)
    .forEach(k => { 
        objects[k].items = objects[k].children; 
        delete objects[k].children; 
    });

Answer №3

Are you considering changing the name from children to items? If so, here are a couple of options for achieving this using JavaScript.

const objs = {
   "one":{
      "title":"bla",
      "amount":5,
      "children":[
         {
            "title":"bla",
            "identifier":"some text"
         },
         {
            "title":"bla2",
            "identifier":"some text2"
         }
      ]
   },
   "two":{
      "title":"bla",
      "amount":5,
      "children":[
         {
            "title":"bla",
            "identifier":"some text"
         },
         {
            "title":"bla2",
            "identifier":"some text2"
         }
      ]
   }
};


for (const obj in objs) {
  objs[obj].items = objs[obj].children;
  delete objs[obj].items;
}

console.log(objs);

Alternatively

const objs = {
   "one":{
      "title":"bla",
      "amount":5,
      "children":[
         {
            "title":"bla",
            "identifier":"some text"
         },
         {
            "title":"bla2",
            "identifier":"some text2"
         }
      ]
   },
   "two":{
      "title":"bla",
      "amount":5,
      "children":[
         {
            "title":"bla",
            "identifier":"some text"
         },
         {
            "title":"bla2",
            "identifier":"some text2"
         }
      ]
   }
};

const newObjs = Object.keys(objs).reduce( (acc, curr) => {
  const updatedObj = { ...objs[curr], items: objs[curr].children };
  delete updatedObj.children
  acc[curr] = { ...updatedObj };
  return acc;
}, {});

console.log(newObjs)

Answer №4

Below is a simple recursive map function that I created in one of my recent answers on Stack Overflow -

const map = (fk = identity, fv = identity, x = null) =>
  Array.isArray(x)
    ? x.map(v => map(fk, fv, v))
: Object(x) === x
    ? Object.fromEntries(
        Object.entries(x).map(([ k, v ]) =>
          [ fk(k)
          , map(fk, fv, v)
          ] 
        )
      )
: fv(x)

Higher-order functions have many practical applications as demonstrated below -

const keyReplacer = (k = "") =>
{ if (k === "title") return "text"
  if (k === "children") return "items"
  else return k
}

const objs = // <-- don't forget const keyword
  { ... }

const result =
  map(keyReplacer, identity, objs)

// => ... 

Execute the code snippet to observe the results -

const identity = x =>
  x
  
const map = (fk = identity, fv = identity, x = null) =>
  Array.isArray(x)
    ? x.map(v => map(fk, fv, v))
: Object(x) === x
    ? Object.fromEntries(
        Object.entries(x).map(([ k, v ]) =>
          [ fk(k)
          , map(fk, fv, v)
          ] 
        )
      )
: fv(x)

const objs = // <-- don't forget const keyword
  {one:{title:"bla",amount:5,children:[{title:"bla",identifier:"some text"},{title:"bla2",identifier:"some text2"}]},two:{title:"bla",amount:5,children:[{title:"bla",identifier:"some text"},{title:"bla2",identifier:"some text2"}]}}

const keyReplacer = (k = "") =>
{ if (k === "title") return "text"
  if (k === "children") return "items"
  else return k
}

const result =
  map(keyReplacer, identity, objs)

console.log(result)


A potential enhancement to this could involve replacing the linear stack of if statements with a more efficient logarithmic dictionary look-up method -

const keyReplacer = (dict = {}) => (k = "") =>
{ const r = dict[k]
  return r === undefined ? k : r
}

const replacements = 
  { title: "text", children: "items" }

const result =
  map(keyReplacer(replacements), identity, objs)

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

The click function for the responsive navbar hamburger is not functioning properly

Having some trouble with the code not working in responsive mode. I've tested it on a 600px screen and the hamburger button doesn't seem to work (I click it and nothing happens). I've gone through both the CSS and JS multiple times but can&a ...

Encountered an issue while attempting to run the npm run serve command on a

I tried running the following commands to create my first Vue app: vue create myfirstapp atom (for open my editor) cd myfirst app npm run serve But I encountered this error: > <a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemai ...

Tips on extracting information from a single JSON object response

I'm currently working on integrating a city search API and have successfully received the JSON Response. However, I'm facing difficulty in parsing the JSON. The error log shows-> 12-19 13:47:24.262 16260-16260/com.example.findloc W/System.er ...

Performing mathematical calculations with numerical values

This piece of code was created as a component of a calculator project for learning purposes. It functions correctly for the most part. However, I noticed that the addition operation seems to concatenate the two numbers together instead of actually adding ...

The Angular date picker is overly verbose in its data output regarding selected dates and requires optimization

Using Angular 5, I have integrated a specific npm package for handling dates import { OwlDateTimeModule, OwlNativeDateTimeModule } from 'ng-pick-datetime'; The problem arises when trying to send data to the server in this required format only ...

Here's a new version: "Utilizing boost::property_tree json to transform values into objects and append members."

My program is designed to make modifications to a JSON document when necessary. It needs to add a child value to another key, regardless of whether it already exists as an object or not. The program should follow these guidelines: If the obje ...

How can you make an element appear when clicking and then disappear with a second click?

Having a bit of an issue here. When I click on the menu button "x," it triggers an onclick event that opens/displays an element. All good so far. But now, I want to click the same menu button "x" to close that same element, and that's where I'm s ...

Ways to send users to a different page with parameters without relying on cookies

Is there a way to redirect users from URLs containing parameters like /?v=xxx to the index page without those parameters showing in the address bar? I still need to retain and use these parameters internally. One approach I considered was using custom hea ...

Transform a JSON array into the jQuery array syntax

Can anyone help me with converting a jQuery JSON object into a jQuery array? Here is the JSON object I am working with: [{"1":"2013-10-12","2":3},{"1":"2013-11-16","2":1},{"1":"2013-12-23","2":3},{"1":"2014-02-11","2":8}] My goal is to convert this JSON ...

I'm facing an issue with my GraphQL resolvers due to a circular dependency

After modifying my repositories to directly return the GQL resolvers, everything was going smoothly until I encountered a circular dependency issue. Now, I have two repositories that rely on each other, creating a dilemma that JavaScript cannot easily reso ...

Can qTip 2.0 be configured to use a different default attribute instead of 'title'?

Is there a way to set qTip to use an attribute other than 'title' as the default? I need to use another attribute because when I disable qtip and add elements dynamically with "title", the title still shows when I hover over the element, which i ...

Is there a way to eliminate the default bootstrap stylings?

Currently working on a project where I am utilizing bootstrap scripts to simplify things. However, upon adding everything along with the CSS, bootstrap ends up changing parts of my page that I did not intend for it to do. Is there a way to remove these u ...

Safari encountering parsing date error

My Angular application is receiving date formats from a web service in the following format: myDate = "2020-03-05T08:00:00" This translates to the fifth of March, 2020 for me For Chrome, Firefox, and IE, the format is yyyy-mm-ddThh:mm:ss However, Safar ...

JavaScript/jQuery countdown timer failing to initialize properly

Having some trouble with a countdown timer that I customized from the original version. The issue seems to be with startCountdown(startDate,deadlineDate,expiredText) as it's returning undefined. Any thoughts on what might be causing this? All relevan ...

What is the best way to extract data from a JSON Instance in Flutter?

Here is the structure of my JSON file: { "feed":{ "entry":[ { "id":{ "$t":"somedata" }, "title":{ "type":"text", "$t":"Stack Smash" }, ...

Ajax requests are returning successful responses for GET and POST methods, however, no response is being received for

When I make a POST request within the same domain ( -> ), the responseXML contains the expected data. However, when I make the same request as a PUT, the responseXML is null for a successful request. I have tried using jQuery.ajax and even implemented i ...

Activate a button by simulating a click event through a shortcut key with the help of a

I have incorporated the hotkeys plugin to enable shortcut functionality on my website. Currently, I am looking for a way to automatically trigger a button click when any shortcuts are pressed. hotkeys.add({ combo: 'alt+1', callback: function (da ...

Preventing a JavaScript timer function from executing multiple times when triggered by an 'in viewport' function

I am trying to create a website feature where a timer starts counting up once a specific div is scrolled into view. However, I am encountering an issue where scrolling away restarts the timer, and I would like the final value that the timer reaches to rema ...

Experiencing difficulties posting on route due to receiving an undefined object instead of the expected callback in Node Js

I am working on implementing a feature in my application where users can create a favorite route. When a user adds a campground to their favorites, the ID of the campground is saved in an array within the schema. The process involves checking if the campgr ...

"Set a timeout for an HTML markup to be displayed in an AJAX

Is there a way to automatically hide the success message that appears after an AJAX request is successful? For example, after 2 seconds of displaying the message, I want it to disappear. Here's the code I have: $.ajax({ url : 'process/regis ...