Search code examples
jsonangulartypescriptadapternested-object

How to map the nested api json response with a model?


I am using the model adapter pattern in angular application. How to map this nested json api response to a model in angular?`

[
    {
        "2023": {
            "stock_market": {
                "January": {
                    "invested": "337",
                    "earned": "332.8"
                },
                "February": {
                    "invested": "306",
                    "earned": "299.4"
                },
                "March": {
                    "invested": "334",
                    "earned": "332.0"
                },
                "April": {
                    "invested": "324",
                    "earned": "319.7"
                }
            }
        }
    },
    {
        "2024": {
            "stock_market": {
                "January": {
                    "invested": "337",
                    "earned": "332.8"
                },
                "February": {
                    "invested": "306",
                    "earned": "299.4"
                },
                "March": {
                    "invested": "334",
                    "earned": "332.0"
                },
                "April": {
                    "invested": "324",
                    "earned": "319.7"
                }
            }
        }
    }
]

I have tried to flattened the object. But not fully understanding how to approach this. also how to modify this above json and use adapter with this below format in angular?

{
  totalInvested: '2334',
  returnPercentage: '4.4%',
  description: 'from last year',
  interpretation: 'good returns',
  title: 'Total profit or loss',
}

Solution

  • you can create TypeScript Interface to represent the data model and then map the nested API JSON response to instances of those classes

     // inteface class
    export interface MonthlyData {
      invested: string;
      earned: string;
    }
    
    export interface StockData {
      [year: string]: {
        stock_market: {
          [month: string]: MonthlyData;
        };
      };
    }
    

    Next, in your Service, import the interfaces and handle the API response:

      // data.service.ts
    import { Injectable } from '@angular/core';
    import { HttpClient } from '@angular/common/http';
    import { Observable } from 'rxjs';
    import { map } from 'rxjs/operators';
    import { StockData } from './app.model';
    
    @Injectable({
      providedIn: 'root'
    })
    export class DataService {
      private apiUrl = 'YOUR_API_ENDPOINT'; // Replace with the actual API endpoint URL
    
      constructor(private http: HttpClient) {}
    
      getStockData(): Observable<StockData[]> {
        return this.http.get<any[]>(this.apiUrl).pipe(
          map(response => this.mapToStockData(response))
        );
      }
    
      private mapToStockData(response: any[]): StockData[] {
        // Mapping logic to convert the API response to StockData[]
        const stockDataList: StockData[] = [];
        for (const data of response) {
          for (const year in data) {
            if (data.hasOwnProperty(year)) {
              stockDataList.push({
                [year]: data[year].stock_market
              });
            }
          }
        }
        return stockDataList;
      }
    }
    

    finally use the service in your component to fetch the data and map it to the method

        // app.component.ts
    import { Component, OnInit } from '@angular/core';
    import { DataService } from './data.service';
    import { StockData } from './app.model';
    
    @Component({
      selector: 'app-root',
      templateUrl: './app.component.html',
      styleUrls: ['./app.component.css']
    })
    export class AppComponent implements OnInit {
      stockDataList: StockData[] = [];
    
      constructor(private dataService: DataService) {}
    
      ngOnInit(): void {
        this.fetchDataFromApi();
      }
    
      fetchDataFromApi(): void {
        this.dataService.getStockData().subscribe(
          (data: StockData[]) => {
            this.stockDataList = data;
            // Now the API response is mapped to the stockDataList array, and you can use it as needed.
          },
          (error) => {
            console.error('Error fetching data:', error);
          }
        );
      }
    }
    

    You can follow this example aswell Try it out

    I hope it will help you thank you :D