Reputation: 20995
I have a bunch of entities I've declared:
export class Meeting implements IHasId {
id = 0;
locationId = 0;
meetTime = new Date();
isFinalized = false;
imageId: number = null;
description = '';
name = '';
}
I have a generic crud service which handles resolving these to its original type
export class ApiResourceBaseService<T extends IHasId> {
get(id: number): Observable<T> {
return this.http.get<T>(`${this.apiUrl}/${this.route}/${id}`);
}
}
Typescript Generics are only superficial, so when I call get<T>
typescript assumes my json is correct. However, My date objects are not resolved properly, they are resolved as string.
I have several entities, It would be annoying to create custom constructors/adapters to parse the dates.
does anyone have a better idea for automatically resolve dates?
Upvotes: 1
Views: 371
Reputation: 20995
I've created an interceptor to transform the data, In the future I'll probably just have auto generate my models and api resources from the api documentation and avoid this but for now I'm just using this hack:
export class ModelBinderInterceptor implements HttpInterceptor {
// regex of ISO 8601 Date.
DATE_TIME_TIMEZONE_REGEXP =
/^(-?(?:[1-9][0-9]*)?[0-9]{4})-(1[0-2]|0[1-9])-(3[01]|0[1-9]|[12][0-9])T(2[0-3]|[01][0-9]):([0-5][0-9]):([0-5][0-9])(.[0-9]+)?(Z)?$/;
constructor() {
}
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return next.handle(req).pipe(tap((event: HttpEvent<any>) => {
if (event instanceof HttpResponse) {
event = event.clone({body: this.modifyBody(event.body)});
}
return event;
}));
}
private modifyBody(body: any) {
return this.deserializeDates(body);
}
private deserializeDates(obj) {
if ((!(obj instanceof Object)) || (isString(obj))) {
return obj;
}
for (const key of Object.keys(obj)) {
const value = obj[key];
let date;
if (isString(value) && (this.DATE_TIME_TIMEZONE_REGEXP.test(value))) {
date = new Date(value);
// the parsing above may fail, in which case we use isNaN to check if the date is valid
if (isNaN(date.getTime())) {
return;
}
obj[key] = date;
}
this.deserializeDates(value);
}
return obj;
}
}
Upvotes: 2