Transform Object Properties into an Object Array

When calling an authentication API, I receive an Observable<any> with the following object:

name: "John"
role: "Admin"

The response may vary in a few ways:

  1. Extra fields could be included;

  2. If a field has multiple values, it is returned as an array:

    email: "<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="b4dedbdcdaf4d1ccd5d9c4d8d19ad7dbd9">[email protected]</a>"   // 1. Extra Field 
    name: "John"  
    role: ["Admin", "Editor"]   // 2. Field now contains 2 values
    

To handle this, I've created an interface:

export class Claim {
  type: string;
  value: string;
}

I need to create an array of Claims based on the object received.

For the first example, the array of Claims would be:

type      value
  
name      John
role      Admin

And for the second example:

type      value 
  
email     <a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="2e444146406e4b564f435e424b004d4143">[email protected]</a>
name      John
role      Admin
role      Tutor         // Multiple claims of same type

Update:

Based on pc_coder's answer, my code looks like this:

getClaims(type: string): Observable<Claim[]> {

  return this.getUser().pipe(map(user => {

    let claims: Claim[] = [];

    Object.entries(user.profile).forEach((element)=>{ 
      if (typeof element[1] == "object") { 
        element[1].forEach(x => { 
          claims.push({ type: element[0], value: x })
        })
      }
      else { 
        claims.push({ type: element[0], value: element[1]})
      }   
    });

    return claims;

  }));

}
 

Can I use RXJS operators to improve the transformation process? Also, is it possible to filter claims by type when the type parameter of getClaims is provided?

Answer №1

Utilize Object.keys or Object.entries to access key names and then their corresponding values. Verify if the value is an object or not, then add it to a new array of objects.

var obj1={email: "<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="d8b2b7b0b698bda0b9b5a8b4bdf6bbb7b5">[email protected]</a>",name: "John" ,role: ["Admin", "Editor"] }
var obj2={email: "<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="f993969197b99c81989489959cd79a9694">[email protected]</a>",name: "John"  }

//using Object.keys
function convertTo(obj){
  var result=[];
  Object.keys(obj).forEach((el)=>{
    if(typeof obj[el]=="object"){obj[el].forEach(x=>{result.push({type:el,value:x})})}
    else{ result.push({type:el,value:obj[el]})}
  })
  return result;
}
//using Object.entries

function convertTo2(obj){
  var result=[];
  Object.entries(obj).forEach((el)=>{ 
    if(typeof el[1]=="object"){ el[1].forEach(x=>{result.push({type:el[0],value:x})})}
    else{ result.push({type:el[0],value:el[1]})}   
  });
  return result;
}
console.log(convertTo2(obj1));console.log(convertTo2(obj2));console.log(convertTo(obj1));console.log(convertTo(obj2));

Answer №2

Attempt

transform data into claims using TypeScript:</br>ToClaims(
    information: {[key:string]: string|string[]}
):Claim[]{
    const outcome=new Array();
    for(const category in information){
        if(information.hasOwnProperty(category)){
            const item = information[category];
            if(Array.isArray(item)){
                for(const value of item){
                    outcome.push({
                        category,
                        value,
                    });
                }
            } else{
                outcome.push({
                    category,
                    value: item,
                });
            }
        }
    }
    return result;
}

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

"Enhancing asynchronous operations in rxjs: creating a forEach loop that can pause and wait

Within my foreach loop, I encountered a situation where I needed to make an HTTP request to fetch certain information. In my attempt to address this issue, I experimented with using a forkJoin within the loop to ensure that it waits for the observables (al ...

Angular 2 encountering an error: "@types module is missing"

After dedicating an excessive amount of time to this issue, I am finally surrendering. The challenge lies in incorporating a module into my angular 2 project: import * as d3ScaleChromatic from 'd3-scale-chromatic'; Unfortunately, this results ...

Tips on concealing the scrollbar only when a particular element is visible

I inserted the following code into my index.html file: <head> <style> body::-webkit-scrollbar { display: none; } </style> </head> This code successfully hides the scrollbar. My goal is to only h ...

What is the best way to find a specific string within an array of strings?

I have a list of tasks as strings: todo=[ 'Get up', 'Brush my teeth', 'Go to work', 'Play games' ]; I am attempting to compare it with this: Template: <input (input)="checkArrays($event)" /> In my ...

Angular2: The NgFor directive is designed to work with Iterables like Arrays for data binding

I'm currently working on a university project to develop a web application consisting of a Web API and a Frontend that interacts with the API. The specific focus of this project is a recipe website. Although I have limited experience with technologies ...

How come TypeScript does not detect when a constant is used prior to being assigned?

There's an interesting scenario I came across where TypeScript (3.5.1) seems to approve of the code, but it throws an error as soon as it is executed. It appears that the root cause lies in the fact that value is being declared without being initiali ...

Instruction to deactivate elements and eliminate additional properties that are marked as [disabled]

I'm encountering a puzzling issue. A directive needs to be implemented that enables or disables UI elements based on the user's role. While it works for UI elements that are not disabled by any other conditions, some buttons become disabled when ...

A destructured object with a Typescript interface

While working on a React / TypeScript project, I encountered an error involving destructuring an object. The issue arises when I try to destructure notificationData within the publish function. An error message stating "Property 'messages' does ...

How can we leverage mapped types in TypeScript to eliminate properties and promisify methods?

Below is the provided code snippet: class A { x = 0; y = 0; visible = false; render() { return 1; } } type RemoveProperties<T> = { readonly [P in keyof T]: T[P] extends Function ? T[P] : never//; }; type JustMethodKe ...

Achieve an overlapping effect between absolutely positioned sibling divs without the need to specify a background color

Exploring the development of a swipe-to-action list component. <div class="list-container"> <div class="row"> <div class="content"> Sample Content 1 </div> <div class="action"> ...

What is the best way to transfer information within the same webpage?

https://i.sstatic.net/umfln.pnghttps://i.sstatic.net/9W6ZE.pngI'm just starting out with angular 2/4 projects and I have a popup search tab in the interface that displays an editable list. However, I am unsure about how to transfer data to the main i ...

Utilize the class type of a method parameter as the method type for another parameter

Here's a quick example illustrating my desired functionality. // Every time, the ACL class will have a different name such as "UsersACL", etc. export class EventsACL { test(): { read: true, write: true } { } } // This function acts ...

Error in Angular ESLint: The key parameter is mandatory

I'm attempting to download a file using the Angular code below, but I consistently receive an error stating Parameter "key" required const headerValues = new HttpHeaders({ 'Content-Type': contentType!, 'Accept': contentTy ...

Managing the rxjs from an Array of observables when the array has no elements

Looking for a more elegant solution to handle the case where an array of observables is empty in the following TypeScript function. I want the observable to complete when subscribe() is called without the need for an initial check. I've already imple ...

Is it more beneficial to use a shared service or pass @Input data between multiple components for optimal practice?

If I inject a service into my main.ts, I can easily access it without the need to declare new providers in my child components. The service contains variables that experience changes. Should I pass these variables down to every child component, grandchild ...

Angular 2 - mastering the art of handling errors

In my Angular 2 application, I have multiple pages that call backend services. My question is how to create a universal error popup component that can display an error message whenever needed across all pages. Can anyone assist me in finding a solution f ...

Is it possible to filter an array of data using a dropdown in Angular without using a pipe?

I am facing an issue with filtering data based on the selected dropdown item. Currently, it only filters the data once when I select a filter, and after that, it always returns an empty result. Here is an example of the code: <select class="select" (c ...

The ng2 Bootstrap modal will not close unless the button has an onclick function attached to it

I have been working on creating a page that displays a list of items. Each item, when clicked, triggers a ng2-bootstrap modal to show detailed information about that specific item. However, I encountered an issue when attempting to use (click)="lgModal.sho ...

Trigger the D3 component to re-render in React after a state change occurs in the parent component

My React project consists of two components written in TypeScript. The first component contains menus, and I am using conditional rendering to display different content based on user selection. <Menu.Item name="graph" active={activeItem ...

What is a more efficient way to optimize the repeating 'for-of' loop?

I am faced with the following code challenge: runA() { const request = []; for (const item of this.items ) { request.push(this.getRequestData(item.prop1)); // want to generalize that } return forkJoin(...request).pipe(x => x); ...