7

I know that json does not treat dates in a special way and provides them as strings from the server. Is there a way to provide a json object response that has an ISO date property and map this to a class already with the date property mapped as a JS date?

Example:

Json Response:

{
    "data": {
        "id": 1,
        "name": "John",
        "surname": "Smith",
        "birthDate": "1986-05-04T22:59:59.000Z"
        "subscriptionDate": "2020-06-28T14:36:43.498Z"
    }
}

And I have this class:

export class User {

    id: string;
    name: string;
    surname: string;
    birthDate: Date;
    subscriptionDate: Date;

}

My service method:

getUser(id: string): Observable<User> {
    return this.http.get<User>(`${this.UrlService}estabelecimentos/${id}`, { headers: this.authenticationService.jwt() }).catch(super.serviceError);
}

But when I use it in my component birthDate and subscriptionDate are always treated as strings. Is there anyway to transform it to JS dates without having to format the date in every each request by iterating the json response and modifying the object?

Philippe Gioseffi
  • 1,488
  • 3
  • 24
  • 41

4 Answers4

4

The short answer is no as JSON format does not allow date types. See this: https://www.w3schools.com/JS/js_json_datatypes.asp

I don't think you have any choice other than to transform them into Date objects, and besides, it's relatively trivial given your string date format:

ndate = new Date("1986-05-04T22:59:59.000Z")
lionbigcat
  • 803
  • 6
  • 13
  • 2
    The problem is not to convert the string into a Date but to do it for multiple fields and classes manually. – Philippe Gioseffi Jul 10 '20 at 06:00
  • So what are you trying to achieve? "Is there anyway to transform it to JS dates without having to format the date in every each request by iterating the json response and modifying the object?" You're asking if you can transform the JSON field into a JS Date object without having to format the date, and the answer is no. JSON data types do not allow date objects as per the link above. – lionbigcat Jul 10 '20 at 06:27
  • 2
    I think angular has mechanisms such as http interceptors that can intercept a response and modify data. That's what I need. – Philippe Gioseffi Jul 10 '20 at 06:37
  • why would you want to use a http interceptor to modify data? Doesn't seem like an Angular best practice to me. Far better to create a service that sits between your Component and API service, and map/transform data there. – lionbigcat Jul 10 '20 at 08:06
3

I suggest to transform the json response before returning it, like this :

getAll(): Observable<Session[]> {
  return this.apiService.get(`/sessions`).pipe(
    map((data)=>{
      return data.map((session) => {
        session.startDate = new Date(session.startDate);
        session.endDate = new Date(session.endDate);
        return session;
      }
    )})
  );
}
Mustapha GANGA
  • 505
  • 7
  • 12
0

JSON doesn't provide any special support for date. You need to convert it manually. As follows:

new Date("1986-05-04T22:59:59.000Z");

Converting JSON object into a Javascript object can help you to achieve what you need.

Check this function:

function convertJsonIntoJavaScript(data){
let newObj = new Object();
   Object.keys(data).forEach(x=> {
   let d = new Date(data[x]);
   newObj[x]= (d instanceof Date && !isNaN(d))? d: data[x];
});
return newObj;
}

NOTE: I have not tested this function, write your feedback in the comment below if it works or not.

Arun Saini
  • 6,714
  • 1
  • 19
  • 22
0

Since the GET is going to return an observable, you should be able to do something like this:

getUser(id: string): Observable<User> {
  return this.http.get<User>(`${this.UrlService}estabelecimentos/${id}`, { headers: this.authenticationService.jwt() })pipe(
    map(response => {
      return {
        "data": {
          "id": response.id,
          "name": response.name,
          "surname": response.surname,
          "birthDate": new Date(response.birthDate)
          "subscriptionDate": new Date(response.subscriptionDate)
      }
    }),
    catchError(()=> super.serviceError)
  )
}
Tucker
  • 1,722
  • 2
  • 10
  • 12