Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Deserialize date from JSON to Date in Typescript

I get from my backend a JSON that looks like this:

[{
    "schedulingId": "7d98a02b-e14f-43e4-a8c9-6763ba6a5e76",
    "schedulingDateTime": "2019-12-28T14:00:00",
    "registrationDateTime": "2019-12-24T16:47:34",
    "doctorViewModel": {
        "doctorId": "a49d9534-65a6-4730-ac45-4dc2f91165e0",
        "doctorName": "Ana"
    },
    "personViewModel": {
        "personId": "3607c475-e287-4e83-85e6-a46f4a0116d6",
        "personName": "João",
        "birthDate": "1970-09-18T00:00:00"
    },
    "consultaViewModel": null
}]

And I need to deserialize that JSON into my Scheduling parsing the date from JSON to 'dd/MM/yyyy hh:MM:ss' format:

export interface Scheduling {
   schedulingId : string;
   schedulingDateTime : Date;
   registrationDateTime : Date;
   person : Person;
   doctor : Doctor;
   consulta? : Consulta;
}

export interface Person {
   personId : string;
   personName : string;
   birthDate : Date;
}

export interface Doctor {
    doctorId : string;
    doctorName : string;
}

export interface Consulta {
    consultaId : string;
    consultaDateTime : Date;
}

But I'm not sure how I can do that after calling my get method:

this.httpClient.get<Scheduling>(`${applicationUrl}/scheduling/${date}`);
like image 682
Rômulo Borges Avatar asked Dec 26 '19 17:12

Rômulo Borges


2 Answers

There are two ways to achieve this, using direct mapping and using constructors,

You can achieve this using pipe and map operator from rxjs/operators

1. Direct mapping

import { map } from "rxjs/operators";

this.httpClient.get<Scheduling>(`${applicationUrl}/scheduling/${date}`)
   .pipe(
        map(scheduling => {
          scheduling.schedulingDateTime = new Date(scheduling.schedulingDateTime);
          scheduling.registrationDateTime = new Date(scheduling.registrationDateTime);
          scheduling.personViewModel.birthDate = new Date(scheduling.personViewModel.birthDate);
          return scheduling;
        })
    );

2. Using constructors

Here will pass each received json to constructor of classes and parse the date in constructor.

export class Person {
  personId: string;
  personName: string;
  birthDate: Date;

  constructor(init: Person) {
    this.personId = init.personId;
    this.personName = init.personName;
    this.birthDate = parseDate(init.birthDate);
  }
}

export class Consulta {
  consultaId: string;
  consultaDateTime: Date;

  constructor(init: Consulta) {
    this.consultaId = init.consultaId;
    this.consultaDateTime = parseDate(init.consultaDateTime);
  }
}

export class Doctor {
  doctorId: string;
  doctorName: string;

  constructor(init: Doctor) {
    this.doctorId = init.doctorId;
    this.doctorName = init.doctorName;
  }
}


export class Scheduling {
  schedulingId: string;
  schedulingDateTime: Date;
  registrationDateTime: Date;
  person: Person;
  doctor: Doctor;
  consulta?: Consulta;

  constructor(init: Scheduling) {

    this.schedulingId = init.schedulingId;

    this.schedulingDateTime = parseDate(init.schedulingDateTime);
    this.registrationDateTime = parseDate(init.registrationDateTime);

    this.person = init.person !== undefined ? new Person(init.person) : undefined;
    this.consulta = init.consulta !== undefined ? new Consulta(init.consulta) : undefined;
    this.doctor = init.doctor !== undefined ? new Doctor(init.doctor) : undefined;
  }
}



export function parseDate(str: string | Date): Date {
  if (str !== undefined && str !== null) {
    return new Date(str);
  }
  return undefined;
}

Service

this.http.get<Scheduling[]>(`${applicationUrl}/scheduling/${date}`)
      .pipe(
        map(schedulings => {
          const modifiedSchedulings = []
          for (const scheduling of schedulings) {
            modifiedSchedulings.push(new Scheduling(scheduling));
          }
          return modifiedSchedulings;
        })
      );
like image 93
Plochie Avatar answered Oct 12 '22 22:10

Plochie


If you convert the interfaces to classes then you can create constructors for them and return the desired response.

Defined the classes:

export class Scheduling {
  constructor(
    public schedulingId: string,
    public schedulingDateTime: Date,
    public registrationDateTime: Date,
    public person: Person,
    public doctor: Doctor,
    public consulta?: Consulta
  ) {}
}

export class Person {
  constructor(
    public personId: string,
    public personName: string,
    public birthDate: Date
  ) {}
}

export class Doctor {
  constructor(public doctorId: string, public doctorName: string) {}
}

export class Consulta {
  constructor(public consultaId?: string, public consultaDateTime?: Date) {}
}

now you can map the response to the defined classes as below:

this.httpClient.get<Scheduling[]>(`${applicationUrl}/scheduling/${date}`).pipe(
  map((schArr: any[]) => {
    const resp: Scheduling[] = [];
    schArr.forEach(sch => {
      resp.push(
        new Scheduling(
          sch.schedulingId,
          new Date(this.datePipe.transform(sch.schedulingDateTime, this.FORMAT)),
          new Date(this.datePipe.transform(sch.registrationDateTime, this.FORMAT)),
          new Person(
            sch.personViewModel.personId,
            sch.personViewModel.personName,
            new Date(this.datePipe.transform(sch.personViewModel.birthDate, this.FORMAT))
          ),
          new Doctor(sch.doctorViewModel.doctorId, sch.doctorViewModel.doctorName),
          sch.consultaViewModel != null
            ? new Consulta(sch.consultaViewModel.consultaId, sch.consultaViewModel.consultaId)
            : null
        )
      );
    });
    return resp;
  })
);

For readability define a constant called format and inject the DatePipe service:

  constructor(private datePipe: DatePipe, private httpClient: HttpClient) {}
  FORMAT = "yyyy-MM-dd HH:mm:ss";

Working Stackblitz

like image 20
Nicholas Kurian Avatar answered Oct 12 '22 22:10

Nicholas Kurian