Unraveling deeply nested object structures within an array of objects

In my Typescript project, I am working with an object structure that looks like this:

    {
  a: "somedata",
  b: "somedata2",
  c: [
    {
      name: "item1",
      property1: "foo",
      property2: "bar",
      property3:{property4:"baz",property5:"foo2"},
      property6:"bar2"
    },
    { name: "item2", properties:{...} },
  ]
};

My goal is to set the properties of each item at the same level in order to achieve this final object structure:

 {
  a: "somedata",
  b: "somedata2",
  c: [
    {
      name: "item1",
      property1: "foo",
      property2: "bar",
      property4:"baz",
      property5:"foo2",
      property6:"bar2"
    },
    { name: "item2",
      property1:"...",
      property2:"..." },
  ]
};

UPDATE: This is where I am currently at with my code:

  getFinalObject(objectId){
    
        return this.http.get(
            this.API_URL + "/object/"+objectId,
            this.getHeaders()
          ).pipe(
            map((res:any) =>{//my final object should be mapped here
});
    }

Answer №1

Here is a versatile function that can handle objects of any depth, barring excessive nesting which could lead to a call-stack overflow.

const flatten = <T extends Record<string, any>>(value: T): Record<string, any> =>
    Object.fromEntries(
        Object.entries(value)
            .flatMap(([k, v]) =>
                typeof v === "object" && v !== null
                    ? (Array.isArray(v)
                        ? [[k, v.map(x => typeof x === "object" ? flatten(x) : x)]]
                        : Object.entries(flatten(v)))
                    : [[k, v]]))

Try it out here

Answer №2

If there are no additional levels of nesting beyond what is shown in the example, and nesting occurs only within the key "c", the code below may address your requirements. The use of type "any" was necessary for declaring the object due to constraints imposed by typescript during deletion and insertion.

let s:any =   {
  a: "somedata",
  b: "somedata2",
  c: [
    {
      name: "item1",
      property1: "foo",
      property2: "bar",
      property3:{property4:"baz",property5:"foo2"},
      property6:"bar2"
    },
    { name: "item2", 
      property1: "foo",
      property2: "bar",
      property3:{property4:"baz",property5:"foo2"},
      property6:"bar2"  
    },
  ]
};

for(let i:number=0; i<s.c.length; i++) {
    let KEYS:string[] = Object.keys(s.c[i]);
    let VALS:string[] = Object.values(s.c[i]);
    let tempKEYS:string[] = [];
    let tempVALS:string[] = [];
    for(let j:number=0; j<VALS.length; j++) {
        if(typeof VALS[j] === "object") {
            tempKEYS.push(...Object.keys(VALS[j]));
            tempVALS.push(...Object.values(VALS[j]));
            delete s.c[i][KEYS[j]];
        }
    }
    for(let j:number=0; j< tempKEYS.length;j++) {
        s.c[i][tempKEYS[j]] = tempVALS[j];
    }
}

console.log(s);

An alternative approach is to utilize an interface and create a new object extracting values from the existing one. This way, the usage of the "any" type can be circumvented.

interface Inner {
    [property : string] : string
}

interface Outer {
    a : string,
    b : string,
    c : Inner[]
}

let s:any =   {
  a: "somedata",
  b: "somedata2",
  c: [
    {
      name: "item1",
      property1: "foo",
      property2: "bar",
      property3:{property4:"baz",property5:"foo2"},
      property6:"bar2"
    },
    { name: "item2", 
      property1: "foo",
      property2: "bar",
      property3:{property4:"baz",property5:"foo2"},
      property6:"bar2"  
    },
  ]
};


let newS : Outer = {
    a : s.a,
    b : s.b,
    c : [] 
};

for(let i:number=0; i<s.c.length; i++) {
    newS.c.push({});
    let KEYS:string[] = Object.keys(s.c[i]);
    let VALS:string[] = Object.values(s.c[i]);
    console.log(VALS.length);
    for(let j:number=0; j<VALS.length; j++) {
        if(typeof VALS[j] === 'string') {
            newS.c[i][KEYS[j]] = VALS[j];
        }
        else if(typeof VALS[j] === 'object') {
            let innerKEYS : string[] = Object.keys(VALS[j]);
            let innerVALS : string[] = Object.values(VALS[j]);
            for(let k:number=0; k<innerKEYS.length; k++) {
                newS.c[i][innerKEYS[k]] = innerVALS[k];
            }
        }
    }
}

console.log(newS);

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

Scrolling horizontally is an option depending on the content displayed on the screen

Imagine having a webpage structured like this: <header>...</header> <body> <section id="A">...</section> <section id="B">...</section> <section id="B2">...</section> <section id="C">...&l ...

Unraveling the Mysteries Behind the .next() Method in Angular

import { Component, Input, Output, EventEmitter } from '@angular/core'; var customInputCss = "app/css/ui/custom-input.css"; var customInputTemplate = "app/partials/custom-input.html"; @Component({ selector: 'custom-input', sty ...

retrieving the configuration settings from my customized service

When attempting to access my custom service within its config property in order to inject an HTTP interceptor, I am encountering the following issue: angular .module("common.services") .factory("redirectService", [" ...

What steps can be taken in Angular to eliminate an additional HTML tag created when using dynamic components with a structural directive?

I currently have a complex infrastructure within my project that includes: host component structural directive used in the host component's template (MyDir) another component used in the structural directive (MyComp) A simplified version is outline ...

What is the best way to display an error message for a dynamic form array in Angular?

I created a dynamic form array where clicking the add contact button inserts a dynamic form field. I successfully implemented validation for the form fields (using validator.required, validator.pattern, etc.). However, when attempting to display an error ...

Naming a JSON object twice

As a newcomer to node.js, I find myself struggling with understanding the process. Can someone please guide me on where I might be going wrong? This is how I create a new Product exports.postAddProduct = (req, res, next) => { const product = new Produ ...

Exploring the world of Node.JS and AngularJS through the integration of API routes

Currently, my backend is built using Node.JS with Express and serving as my API servlet. On the frontend, I'm utilizing AngularJS for the user interface. After numerous searches on Google, I was able to resolve an issue where I faced challenges using ...

Cookie Session did not generate following a successful login

Hey there, I'm currently working on a MERN stack project where users can register and log in. However, I'm encountering an issue - even though the user successfully logs in, a session cookie is not being created. I've used the same logic in ...

Rearrange DIV elements by clicking a button that redirects you to a different webpage

Consider a scenario with two distinct pages: website.com/page1 website.com/page2 Page 1 contains multiple buttons, each leading to Page 2. On Page 2, there are various content sections (divs). Is there a straightforward meth ...

Troubleshooting: Difficulty with Angular 2 TypeScript interface array functionality

Currently, I am developing an Angular 2 application where I aim to showcase messages by utilizing an interface and storing all the messages in an array. Below is a snippet of my TypeScript component that highlights this functionality: export class ChatCom ...

Invalidating the express response object due to a TypeError issue

Currently, I am in the process of writing a test that utilizes sinon and sinon-express-mock to mock an incorrect request. The goal is to then call a validation function within my application and verify that it returns the expected response status code (400 ...

Retrieve the image information from a specified element in the Document Object Model

Is it possible to extract the image data of a DOM element using standard JavaScript or browser extensions? I'm considering scenarios where: Creating an offscreen DOM element Populating it with dynamically styled CSS content Retrieving its image dat ...

The import 'react-router' does not include an export called 'browserHistory'. This issue is coming from the /src/App.js file

I've recently started diving into the routing section of learning react, but I'm a bit puzzled by the error message I encountered. Error: Failed to compile ./src/App.js 31:19-33 'react-router' does not contain an export named 'bro ...

Execute and generate a continuous loop in JavaScript

I successfully implemented an image slider using pure PHP, but encountered issues when integrating it into Yii framework. The images were not loading due to the following reasons: - JavaScript block was not loading image numbers. - I am unsure how to load ...

Testing network connection using alert feature in Ionic 2

Looking to verify network connectivity with an alert in Ionic 2. While this guide was helpful, it is quite outdated now and Ionic 2 syntax has evolved. Despite modifying the Alert component as suggested in the comments, I'm still encountering errors. ...

What is the role-based menu item feature and routing in Angular 14?

My Angular App is running version 14. The header contains links for Register, Login, Add New Employee, List of Employees, Update Employee Profile, Employee Profile, Working Hours, and Logout. https://i.sstatic.net/M1len.png If a user with an Admin role l ...

Having trouble with Pie Chat not displaying on my browser while working on D3 integration with basic HTML

I am struggling to get my Pie chart created using D3.JS to show up when I load my file in Chrome or any browser (index.html). It only displays the title without the actual pie chart. I'm not sure where the issue lies and why my pie chart is not appea ...

VueJS - Vuefire - Unexpected Error: document.onSnapshot is not a valid function

I'm currently working on integrating Vuefire into my project. I have been following the instructions provided on the Vuefire website, but I am encountering an error. db.js: import firebase from 'firebase/app' import 'firebase/firestore ...

Enhance your message inbox experience with jQuery/Javascript features inspired by Gmail, including the ability to select all messages with a checkbox and

It is truly satisfying to be here working on developing a private message inbox for my website, especially after successfully implementing a complete user signup/login and activation system. A few months ago, I never believed I had enough patience to grasp ...

Error: Undefined reference to OnInit in Angular 2

I'm currently working on implementing the angular 2 onInit feature, but I keep encountering an error in the console: Error: ReferenceError: OnInit is not defined(...) Could someone please help me identify what mistake I may be making? Below is my ...