2

I have this interface

export interface Student {
    cf: string,
    firstName: string,
    lastName: string,
    dateOfBirth: Date,
    description?: string,
    enrollmentDate?: Date
}

I want to populate an array of students with a http get request, which returns the following json for each student

{cf: "blablabla", first_name: "Mario", last_name: "Rossi", date_of_birth: "1998-01-24", enrollment_date: "2019-03-20" },

As you can see, the interface has different names from the response (firstName instead of first_name), so when I print to the console the names of the students I get undefined.

This is the service function from which I get the data

  getStudents(): Observable<Student[]> {
    return this.httpClient.get<Student[]>(this.studentsUrl, this.baseService.httpOptions);
  }

And here is my students component

export class StudentsComponent implements OnInit {

  students: Student[];
  childIcon = faChild;
  plusIcon = faPlus;
  private _newStudent: boolean = false;

  constructor(private studentsService: StudentsService) { }

  ngOnInit(): void {
    this.studentsService.getStudents().subscribe(
      (result: Student[]) => {
        this.students = result;
        this.students.forEach(student => console.log(student));
      },
      error => console.log(error)
    )
  }
}

Is there a way to convert the json response to my Student interface? Several answers on stack overflow suggest map is the way, but I don't understand how to use that operator alog with subscribe

dc_Bita98
  • 851
  • 2
  • 17
  • 35

1 Answers1

2

One way would be manually loop through the array and define new keys and delete obsolete ones before returning the array using RxJS map.

Service

import { pipe } from 'rxjs';
import { map } from 'rxjs/operators';

getStudents(): Observable<Student[]> {
  return this.httpClient.get<Student[]>(this.studentsUrl, this.baseService.httpOptions).pipe(
    map(response => response.forEach(student => {
        student.firstName = student.first_name;
        student.lastName = student.last_name;
        student.dateOfBirth = student.date_of_birth;
        student.enrollmentDate = student.enrollment_date;
        delete student.first_name;
        delete student.last_name;
        delete student.date_of_birth;
        delete student.enrollment_date;
      });
    )
  );
}

But depending on the number of elements in the array, this could be a heavily taxing operation for a single HTTP request. Couldn't you define the interface definition to match the one of the API?

ruth
  • 29,535
  • 4
  • 30
  • 57
  • Interesting solution, although I don't understand the need for deleting the keys. Anyway yes, surely I can match the interface to the one on the API, and I think I'm going for this way. My question was because I'm new to Angular and I want to consider every possible solution – dc_Bita98 May 02 '20 at 14:23
  • 1
    Without deletion both the forms of keys will persist. For eg., both `firstName` and `first_name`. There is no built-in way of renaming object keys in Javascript. – ruth May 02 '20 at 14:24