Home > other >  Typescript (Angular) - JSON model Deserialisation
Typescript (Angular) - JSON model Deserialisation

Time:11-30

I would like to add and populate additional fields (which are not sent by backend service) in my http model. Catch is that I am not able to populate (map) those fields in the place where http response is being received since I am using internal framework.

Is there a possibility in Typescript (Angular) to somehow override JSON Deserialisation flow/Instance creation and populate mentioned fields. For example:

interface ElectricDevice {
    
    energy_meter_start: number; // received from backend service
    energy_meter_stop: number; // received from backend service

    energy_spent: number; // not received by backend service, but needs to be populated as energy_meter_stop - energy_meter_start

    // ...

    /* I would like to somehow populate energy_spent as energy_meter_stop-energy_meter_end on instance creation (deserialisation) */

}

CodePudding user response:

You need a HttpInterceptor, in which you can manipulate data.


@Injectable()
export class CustomJsonInterceptor implements HttpInterceptor {
  constructor(private jsonParser: JsonParser) {}

  intercept(httpRequest: HttpRequest<any>, next: HttpHandler) {
    if (httpRequest.responseType === 'json') {
      // If the expected response type is JSON then handle it here.
      return this.handleJsonResponse(httpRequest, next);
    } else {
      return next.handle(httpRequest);
    }
  }

Read more about it in the tutorials: https://angular.io/api/common/http/HttpInterceptor

CodePudding user response:

I have asked you for the especific names of your services.

But, in the meantime, I give you a 'general' answer to your question. You just need to do this:

this.yourService.yourGetElectriceDevices
.pipe(
   map (_resp: ElectricDevice  => _resp.energy_spent = _resp.energy_meter_stop - _resp.energy_meter_start
)
.subscribe( resp => { //your treatment to the response });

This above, only works for a rapid test. If you want to do somethig more 'elaborated', you could transform your interface into a class, and add your calculated attribute, something like this:

export interface ElectricDevice {
    
    energy_meter_start: number; // received from backend service
    energy_meter_stop: number; // received from backend service
  
}

export Class ElectricDeviceClass {

energy_meter_start: number;
energy_meter_stop: number;

energy_spent: number; 


constructor (data: ElectricDevice)  {
   this.energy_meter_start = data.energy_meter_start;
   this.energy_meter_stop= data.energy_meter_stop;

   this.energy_spent = this.energy_meter_stop - this.energy_meter_start;
}

And for using it, just:

import { ElectricDeviceClass, ElectricDevice } from './../model/...' // There where you have yours interfaces and model classes

this.yourService.yourGetElectriceDevices
.pipe(
   map (_resp: ElectricDevice  => new ElectricDeviceClass(_resp)
)
.subscribe( resp => { //your treatment to the response });
  • Related