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