Enhance JSON for efficiency in Typescript Mapping

In my Java to Typescript data transfer, I am encountering an issue with objects containing "Map" properties. To define my Typescript models, I use interfaces instead of classes:

export interface Foo {
    bar: Map<string, Bar>;
    mapOfBar: Map<string, Map<string, Bar>>;
}

export interface Bar {
    someField: string;
}

To handle the JSON object and convert it to type Foo, I implemented the following code:

import {HttpClient} from '@angular/common/http';
...
export class FooService {
    constructor(private http: HttpClient) {
    }

    getFoo(): Observable<Foo> {
        return this.http.get<Foo>('/some/route/to/FooEndpoint');
    }    
}

The issue arises when bar and mapOfBar are returned as type object instead of Map. After extensive research, I came up with a solution by modifying my conversion logic as follows:

    getFoo(): Observable<Foo> {
        return this.http
            .get<Foo>('/some/route/to/FooEndpoint')
            .pipe(
                map((res: Foo) => {
                    res.bar = new Map(Object.entries(res.bar));

                    let actualMapOfBar = new Map(Object.entries(res.mapOfBar));
                    res.mapOfBar = new Map();
                    for (let [key, bar] of actualMapOfBar) {
                        res.mapOfBar.set(key, new Map(Object.entries(bar)));
                    }

                    return res;
                })
            );
    }

Although this approach successfully returns bar and mapOfBar as Maps, it feels inefficient and cumbersome.

As someone who pays attention to detail, I find this method clunky and not ideal for deeply nested object structures.

Are there better ways to tackle this issue? Is there a more efficient or automated method to leverage Typescript interfaces for object conversion?

(Using Angular 9.1, Typescript 3.8, rxjs 6.5)

EDIT: Here is an example response from the endpoint:

{"bar":{"key1":{"someField":"A"},"key2":{"someField":"B"},"key3":{"someField":"C"}},"mapOfBar":{"A":{"key1":{"someField":"A"},"key2":{"someField":"B"},"key3":{"someField":"C"}},"B":{"key1":{"someField":"A"},"key2":{"someField":"B"},"key3":{"someField":"C"}},"C":{"key1":{"someField":"A"},"key2":{"someField":"B"},"key3":{"someField":"C"}}}}

Answer №1

There is no automatic method for converting the response of an API to specific types in TypeScript. When you use the map((res: Foo) line, you are essentially informing the compiler that the data is of type 'Foo', even though it may just be a plain JSON object from the API.

In order to ensure type safety, you will need to manually create interfaces for both the API response and the desired converted type. This is necessary because TypeScript types are only enforced during compile time, and get lost during runtime when consuming APIs.

Instead of trying to convert everything into maps, consider keeping the data as objects and adjusting your typing accordingly:

export interface Foo {
    bar: Record<string, Bar>;
    mapOfBar: Record<string, Record<string, Bar>>;
}

export interface Bar {
    someField: string;
}

Answer №2

Is there a more efficient way to implement this or is there a way to optimize it further? Is there perhaps a simpler method using the Typescript interface to convert the object automatically?

Indeed, there is! Introducing magicJSON - a versatile tool for seamless mapping between JSON data and objects.

npm install magicJSON

You can perform mappings in various ways, such as:

let newObject = new YourClass().fromMagicJSON(jsonData);

Alternatively, you can effortlessly transform a promise's data like this:

http.YOUR_REQUEST_CODE_HERE
    .as(YourClass)
    .[then/pipe/whatever](newObject => { ... })

For more information, refer to the official documentation.

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

Upon receiving the API response, my Angular webpage is failing to redirect to a different page

After executing my code in TypeScript, I encountered an issue with the updateProduct method calling the API to update a product based on form values. The update functionality works fine, but afterwards, I am receiving the following error: error: SyntaxErr ...

Creating both Uniform and Varying drawings on a single webGL canvas

My goal is to create this specific illustration. https://i.sstatic.net/5AfdW.png This project requires the usage of TypeScript. The Code: The code is organized across multiple files. Within the scenegraph file, there's a function that visits a gro ...

Guide on integrating google play services into a nativescript plugin seed?

I am developing a plugin for NativeScript using the recommended nativescript-plugin-seed available at this link. In my plugin, I require access to the Google Location service, but I am facing issues with accessing it. In order to implement the required de ...

How to parse a JSON string into an integer using PySpark

Is there a way in pyspark to convert a string object from a JSON file into an integer? df1.select(df1["`result.price`"]).dtypes Out[15]: [('result.price', 'string')] df1=df1.withColumn(df1.select(df1["`result.price`&quo ...

"I would like to implement ngClass in Angular to display the 'active' status in red and the 'inactive' status in black

I need to implement ngClass in Angular so that the current status is displayed in red color while all other statuses are displayed in black. How can I achieve this? <div *ngFor="let item of status_history; let i = index"> ...

How can I use JavaScript to retrieve the current time from the time.nist.gov NTP server?

Looking for guidance! I'm new to coding and would greatly appreciate detailed instructions and examples. I've been struggling for hours trying to solve this issue - the online resources I found have not been helpful at all. Unfortunately, I don&a ...

Disqus API returning empty JSON response

I'm attempting to retrieve the number of comments from a thread on Disqus, however, the json_decoded response is consistently returning NULL. Even when I echo $data before json_decode it, I receive a string that appears to be valid JSON, indicating th ...

What are the circumstances under which JavaScript GCP libraries return null values?

My current project involves working with GCP and Firebase using typescript. I have been utilizing the provided libraries, specifically version 8 of Firebase, and have encountered some unexpected behavior. For instance (firebase, ver. 8.10.1) import 'f ...

Is it possible to use the inheritance type for a function parameter derived from an object?

When working with Angular, I have been using TypeScript for some time now. Previously, I used to set function parameter types in a hardcoded way, as shown below: login(email: string) {} However, I recently tried to inherit from another object and changed ...

The Angular 11 library module has been successfully imported into the consuming app but it is not being utilized

Currently, I am in the process of creating an Angular library that will encompass services, pipes, and directives to be utilized across various Angular projects within my organization. At this point, I have successfully implemented three services within th ...

Tips for identifying when a div reaches the top or bottom of the browser window in Angular 4

This question has solutions available for JQuery (which I prefer not to use in the current project) and Angular1 (which I am unfamiliar with). ...

Populate a template with data fetched from a URL into an observable array

After completing the interactive tutorials on knockoutJS, I am a newcomer to this framework and found the tutorials to be extremely informative. While reading a few posts, one in particular caught my attention: KnockoutJS observableArray with template a ...

Implementing Angular 4 on a Node Express server within Firebase platform

After setting up an angular 4 project using angular cli, I decided to incorporate express into my application. I created a file named app.js with the following content: app.js const express = require('express') const app = express() ...

The type 'Event' argument cannot be assigned to the 'InfiniteScrollCustomEvent' parameter

I'm facing an issue with Ionic Angular. Here is my movies.page.html: <ion-header> <ion-toolbar color="primary"> <ion-title>Trending Movies</ion-title> </ion-toolbar> </ion-header> <ion-content ...

Deciphering unconventional JSON into an array or object

Here is a sample string that needs to be converted into an array: ['key1':'value1', 2:'value2', 3:$var, 4:'with\' quotes', 5:'with, comma'] The desired array format should look like this: $pars ...

Creating JSON limits in Discord: A simple guide

Recently, I've been focusing on enhancing my understanding of limitations and parsing when it comes to converting data to JSON format. Before delving deeper into the code, let's take a look at the test data provided (Two different sets of data): ...

Navigating JSON Levels in Swift with Codable

I am interested in utilizing the Pokémon API to retrieve data and transform it into a Swift Pokemon structure. Upon fetching information for Pokemon #142, here is a snippet of the response received: { "id": 142, "name": " ...

The command 'ng' is not valid in this context, please make sure it is being used correctly within the program or batch file

After attempting to install angular-cli with npm install -g, I hit a roadblock. Next, I attempted to add it to the PATH under Environment Variables but encountered no success. https://i.sstatic.net/uhuhN.png https://i.sstatic.net/zHGBk.png ...

Leveraging ts-loader alongside strip-loader in Webpack

I am currently facing an issue with strip-loader in my Typescript project that is built with Webpack. The ts-loader statement in my project is as follows: { test: /\.ts$/, loader: 'babel-loader?presets[]=es2015!ts-loader' } Everything see ...

Tips for ensuring the JSON file format remains intact when utilizing the Json.net library to add a new entry to an existing JSON file

my information in json format [ { "name" : "student1", "grade" : "A" }, { "name" : "student2", "grade" : "B" } ] My code for writing the new student data using (FileStream fs = File.Open(WebConfigurationManager.AppSettings["JsonFileL ...