Home > Software engineering >  How to get a typed response from json-ld and hydra in Angular 13?
How to get a typed response from json-ld and hydra in Angular 13?

Time:06-24

I'm trying to make a paginated table in Angular. For that I'm using a backend which returns a json-ld and hydra context response. I want to map that to a model. Typed responses with regular json works fine, but the problem arises with json-ld/hydra context.

I need to get a typed response from the format at the bottom of this post. This is what I have so far:

A list interface

export interface List<T> {
  totalItems: string;
  members: T[];
}

Company model

export class CompanyModel {

  id: number | null;
  companyName: string;
  logoUrl: string;
  users: any;

  constructor(id: any = 0, companyName: string, logoUrl: string, users: any) {
    this.id = id;
    this.companyName = companyName;
    this.logoUrl = logoUrl;
    this.users = users;
  }
}

And a service (CompanyService) which has a get() function to retrieve all (paginated) models.

  get(): Observable<any> {
    return this.http.get<List<CompanyModel>>(this.endpoint   "/companies", {
      headers: new HttpHeaders({
        'Accept':  'application/ld json'
      })
    });
  }

This is the response I get:

@context: "/api/contexts/Company"
@id: "/api/companies"
@type: "hydra:Collection"
hydra:member: [{@id: "/api/companies/1", @type: "Company", id: 1, companyName: "Huels-Weber",…},…]
hydra:search: {@type: "hydra:IriTemplate", hydra:template: "/api/companies{?companyName}",…}
hydra:totalItems: 500
hydra:view: {@id: "/api/companies?page=1", @type: "hydra:PartialCollectionView",…}

I need the totalItems and members to be mapped to an object as I've explained above. How do I do that?

CodePudding user response:

If you mean to map the server response to fit the List<CompanyModel> type

It can be done using the rxjs map operator

 get(): Observable<any> {
    return this.http.get<List<CompanyModel>>(this.endpoint   "/companies", {
      headers: new HttpHeaders({
        'Accept':  'application/ld json'
      })
    }).pipe(
        map((res: any) => ({
          totalItems: res['hydra:totalItems'],
          members: res['hydra:member'],
        }))
      );
  }

Edit

You can update the List interface so that you don't have to map anything..

export interface List<T> {
  'hydra:totalItems': number;
  'hydra:member': T[];
}

CodePudding user response:

You can parse Rest API response and map to your app's schema :

get(): Observable<List<CompanyModel>> {
  return this.http.get<any>(this.endpoint   "/companies", {
    headers: new HttpHeaders({
      'Accept':  'application/ld json'
    })
  }).pipe(
    map((json: any) => {
      const members: CompanyModel[] = json['hydra:member'].map(jsonMember =>({
        id: jsonMember.id,
        companyName: jsonMember.companyName,
        ...
      });

      return {
        totalItems: json['hydra:totalItems'],
        members
      }
    })
  );
  }

Of course this could be improved by :

  • including a typescript model of your 'JSON-LD' response
  • checking if input data are well formatted, with correct values

Hope this will help.

  • Related