Tips for synchronizing response JSON with TypeScript interface in Angular 6

I am retrieving a list of files that have been uploaded from a backend endpoint, and it comes back in this format:

[
    {
        "filename": "setup.cfg",
        "id": 1,
        "path": C:\\back-end\\uploads\\setup.cfg",
        "uploaded_at": "Fri, 01 Jun 2018 09:25:19 -0000"
    },
    {
        "filename": "57760713_1467275948.jpg",
        "id": 2,
        "path": "C:\\back-end\\uploads\\57760713_1467275948.jpg",
        "uploaded_at": "Mon, 04 Jun 2018 09:09:59 -0000"
    },

    .
    .
    .

]

Along with this data, I have a TypeScript interface designed like so:

export interface UploadModel {
    id: number;
    name: string;
    path: string;
    uploadedAt: Date;
}

The issue lies in the naming conventions used; the returned data follows snake_case as uploaded_at while my interface uses camelCase as uploadedAt.

I'm looking to fetch this information from the backend using the following code snippet:

  getUploads(): Observable<UploadModel[]> {
    this.http.get(UPLOADS_ENDPOINT)
     .map((response: Response) => {

         // Need to parse the JSON response here and return an array of UploadModels

     });
  }

Any tips on how to effectively map these two representations without manually iterating through the array of JSON objects?

Answer №1

A custom function can be created to convert keys from underscored format to camel case. Although the provided implementation is basic, it can be enhanced for better efficiency and potentially recursive handling of nested objects.

const data = [
  {
    "filename": "setup.cfg",
    "id": 1,
    "path": "C:\\back-end\\uploads\\setup.cfg",
    "uploaded_at": "Fri, 01 Jun 2018 09:25:19 -0000"
  },
  {
    "filename": "57760713_1467275948.jpg",
    "id": 2,
    "path": "C:\\back-end\\uploads\\57760713_1467275948.jpg",
    "uploaded_at": "Mon, 04 Jun 2018 09:09:59 -0000"
  }
];

function underscoreToCamel(key: string) {
  return key.replace(/_([a-z])/g, function (g) { return g[1].toUpperCase(); });
}

function convertKeys(input: any[]) {
  const output = [];
  for (const item of input) {
    const obj = {};
    for (const key in item) {
      obj[underscoreToCamel(key)] = item[key];
    }
    output.push(obj);
  }
  return output;
}

const result = convertKeys(data);
console.log(result);

Output:

[
    {
        "filename":"setup.cfg",
        "id":1,
        "path":"C:\\back-end\\uploads\\setup.cfg",
        "uploadedAt":"Fri, 01 Jun 2018 09:25:19 -0000"
    },
    {
        "filename":"57760713_1467275948.jpg",
        "id":2,
        "path":"C:\\back-end\\uploads\\57760713_1467275948.jpg",
        "uploadedAt":"Mon, 04 Jun 2018 09:09:59 -0000"
    }
 ]

Answer №2

Unfortunately, there is no simple solution available.

It may be challenging to deal with your response right now, but avoiding it will only make things more difficult in the long run.

Here are three possible approaches you can consider:

  1. You could create two distinct interfaces - IUploadResponse and IUpload. Objects that implement these interfaces will need to have explicit mappings set up in their constructors.

  2. An alternative option is to design an abstract class with a transformation method that handles the mapping process.

  3. Another approach would be to develop a converter that transforms snake_case variables into camelCase format. While this method offers reusability, keep in mind that it may limit certain naming conventions like renaming filename to name. Additionally, this approach does not directly create objects, so you may not access features like typeof or instanceof.

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

What steps are required to configure angular-eslint for a protractor project?

I am in the process of transitioning to eslint using angular-eslint due to TSLint being deprecated. While going through the documentation, I noticed that there is no mention of protractor. My question is, can the default .eslintrc.json configuration be use ...

Creating a new formGroup and submitting it with model-driven form in Angular 2

Adding New Entries to FormArray Using input Field If I want to add values to an existing array through a form input, I can utilize the (click)="addAddress()" in the HTML file and define addAddress in the component.ts to update the values in an array withi ...

Experience the power of Stimulsoft reporting integrated with Angular and Asp.net Core-framework!

I've created a Webservice in Asp.net Core to generate reports which is then called in an Angular app to display the reports. However, when I try to show the report in Angular, it only shows a blank page. What could be causing this issue and how can I ...

Creating a TypeScript interface for Immutable.js objects: A step-by-step guide

Imagine we are working with the following interface User: interface User { id: number; name: string; bag: Item[]; } Now, let's create a React component: interface UserComponentProps { user: User; } interface UserComponentState {} class Use ...

Issue with Angular authentication during login attempt

I am a beginner in Angular and I'm using this method to allow users to log into the system. loginuser(){ const user = { username: this.username, password: this.password }; this.Auth.loginUser(user).subscribe((res)=>{ ...

Creating a global variable in Angular that can be accessed by multiple components is a useful technique

Is there a way to create a global boolean variable that can be used across multiple components without using a service? I also need to ensure that any changes made to the variable in one component are reflected in all other components. How can this be ac ...

Incorporating ngrx/Store into a current Angular application

Currently, I am working on an Angular 7 project that consists of numerous components communicating with an API to update data. The constant refreshing of the data using setTimeout has made it quite overwhelming as all the components are pulling data from t ...

Extracting information from AJAX calls using a DataTable

When it comes to creating CRUD tables in school, I've always used scaffolding per page. However, I recently wanted to experiment with performing all operations without using Partial View. I decided to implement AJAX by following a tutorial on Everyth ...

Encountered issue while transferring the result of urllib.urlopen to json.load

Trying to learn Python and utilizing urllib to download tweets, I encountered a recurring error while following a tutorial. Here is the code snippet causing the issue: import urllib import json response = urllib.urlopen("https://twitter.com/search?q=Micro ...

Utilizing jQuery to process JSON data by extracting a single response from an array

Struggling to populate two areas within a section using JSON response data. Despite receiving the correct response, I am unable to extract and utilize the title, text, and image from data[0] and data[1. The console.log response appears to be undefined. Th ...

Exploring the possibilities of combining AngularJS and Angular 2 routing with wildcard paths

I'm struggling with wildcard path routing in an app that's partially upgraded from AngularJS to ng2. Combining both types of routing involves the following: The initial step in creating a dual router setup is to include an Angular root comp ...

Problematic Angular 6 Lazy Loading Situation

Below is the code snippet I am using for lazy loading: const routes: Routes = [ { path: '', redirectTo: '/home', pathMatch: 'full' }, { path: 'home', component: HomeComponent }, { path: 'manager', lo ...

Guide on refreshing an Angular 2 application after a user has logged out

Is there a way to refresh my Angular 2 application once a user clicks on the logout button? I want all current data in the app to be cleared and then load a sign-in form from the server. Currently, when I click on the logout button, I receive the response ...

Using an Angular interface for an HTTP request: The statusText message reads as "Error: Unable to Determine."

I've been working on calling an API as an example in Angular using an interface. The API I'm trying to access is located at https://jsonplaceholder.typicode.com/posts. Unfortunately, I encountered the following error message: ERROR HttpErrorResp ...

Is it possible to have a button within a table that, when clicked, opens a card overlaying the entire table?

I'm having an issue with a table and card setup. When I click the button in the table, the card that appears only covers part of the table. I want it to cover the entire table area based on the content inside the card. How can I make this happen? I&a ...

Executing observables sequentially based on their dependencies

Looking for guidance on how to accomplish the task mentioned in the title. Here's my situation. I have three methods in my service: isUserEnable(), isLicenseStatusEnable(), and resetPassword(), which need to be executed sequentially. Firstly, I must e ...

Unable to retrieve the key value from a child object in Angular 2 when working with JSON Data

Currently, I am using Angular and attempting to extract data from the child object's key value. Here is the JSON data provided: "other_lessons": [ { "id": 290, "name": "Christmas Test #290", "course": { "id": ...

Exploring TypeScript: A Study on Interfaces and Abstraction

I am working with TypeScript and have created four different entities (models) as shown below: Base model definition: export interface BaseModel { id: string; entityId: string; entityName: string; } Child Model 1: import { BaseModel } from ' ...

How can we retrieve URL parameters with the help of ActivatedRoute in Angular?

My current route configuration is as follows: { path: "events", component: SkeletonComponent, children: [ { path: ':id', component: ViewEventComponent } ] } The constructor of my component looks ...

Is there a way to maintain formdata between components in Angular?

With only the tools of @Input, @Output, routing, and activatedRoute at my disposal, I set out to create a dynamic application. In this project, there are two crucial components: addbook and showbook. The addbook component features a form with a submit bu ...