Damon
Damon

Reputation: 4524

How can I use JSON:API along with Angular/RxJs?

I have a (Laravel) API that is following json:api spec. Everything is working great—using Postman I'm able to make requests for related resources and such.

I am using Angular for my front-end, but I'm struggling to understand how to consume this api.

I have been reading through this SO thread as a starting point.

I am using ngrx for state management; I'm able to successfully make the appropriate request(s) needed to get data from my api. Where I am struggling is how to properly handle the response.

Here is an example response from my request to get an organization:

// response from /api/v1/organization/:id

data: {...}
jsonapi: {...}
links: {...}

Here is my Organization interface:

export interface IOrganization {
    data: object;
    jsonapi: object;
    links: object;

    // before json:api I would just use the below attributes
    id?: string;
    name: string;
    streetAddress1: string;
    createdAt?: Date;
    updatedAt?: Date;
    deletedAt?: Date;
}

Before using json:api, this class was super straight-forward. But since all of the data is now inside of data.attributes I'm not sure how to correctly structure this interface.

Here is what a good portion of my organization.effects file looks like:

return this._organizationService
    .getOrganization(action.organizationId)
    .pipe(
        tap((organization) => {
            console.log(organization);   // {data:{...}, jsonapi: {...}, data:{...}
        }),
        map((organization) =>
            OrganizationApiActions.loadOrganizationSuccess({
                organization,
            })
   ),
   catchError((error) => {...}
    ...

Is the solution to just drill down through the attributes here?

organization.data.id;
organization.data.attributes.name;

Or is there a more logical way to consume this api? I have seen the ngx-jsonapi package. I don't know if that's overkill here?

In the past using vue.js I have just used the jsona npm package

What is the ideal way to consume a json:api (rest api)?

Upvotes: 1

Views: 166

Answers (1)

Andrew Allen
Andrew Allen

Reputation: 8052

If you're not directly consuming the api as is (backend for frontend) then

  • have 2 interface models,
    • one that describes the backend response (ideally codegen or inferred rather than manually written)
    • and the frontend model you want to map to
    • use a function that maps backend object to frontend
    • use on receiving response.
const mapJsonApiToOrganization = () =>
  map((response: OrganizationResponse) => {
    const { id, attributes } = response.data;
    return {
      id,
      name: attributes.name,
      streetAddress1: attributes.streetAddress1,
      // ... other mappings
    };
  });

// In your effect
return this._organizationService.getOrganization(action.organizationId).pipe(
  mapJsonApiToOrganization(),
  // from here frontend model only
  map((organization: Organization) => OrganizationApiActions.loadOrganizationSuccess({ organization })),
);

Imo I would keep data passed to ngrx frontend model only. If you change your backend you'd want to only change the mapping function.

Using 3rd party packages is a judgement call. If it's just those 5 properties for the frontend model drilling seems fine.

Upvotes: 2

Related Questions