jsonangularjson-api

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)?


Solution

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

    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.