0

I'm building an api and I'm trying to handle the following problem:

The client sends the Accept header with application/vnd.api+json, so I reply with the resource in the JSON:API format.

Given are for example the following tables:

  • Author
  • Article

which have a 1:n-relation - so for example one author wrote 100 articles.

My goal is:

GET /author

returns the author (resource object) with a defined number of articles (relationship resource objects) - for example the first 3 articles he wrote.

In this format:

{
  "links": {
    "self": "http://example.com/author",
    "next": "http://example.com/author?page[offset]=2",
    "last": "http://example.com/author?page[offset]=10"
  },
  "data": [
    {
      "type": "author",
      "id": "1",
      "attributes": {
        "name": "Arthur"
      },
      "relationships": {
        "article": {
          "count": 100,
          "links": {
            "self": "http://example.com/author/1/relationships/article",
            "related": "http://example.com/author/1/article"
          },
          "data": [
            {
              "type": "article",
              "id": "4",
              "attributes": {
                "title": "1 reason why I should use json:api"
              },
              "links": {
                "self": "http://example.com/article/4"
              }
            },
            {
              "type": "article",
              "id": "7",
              "attributes": {
                "title": "2 reasons why I should use json:api"
              },
              "links": {
                "self": "http://example.com/article/7"
              }
            },
            {
              "type": "article",
              "id": "42",
              "attributes": {
                "title": "3 reasons why I should use json:api"
              },
              "links": {
                "self": "http://example.com/article/42"
              }
            }
          ]
        }
      }
    }
  ]
}

My idea:

Use a query parameter like

http://example.com/author?relationship[]=article,orderby=date,asc=true,limit=3

tl;dr:

What is the proper way to limit/paginate related resources in the JSON:API format?

Tries
  • 3
  • 5

2 Answers2

2

The spec does not cover pagination and sorting of included related resources. I would recommend to not include the related resources but using a relationship link instead if you need pagination or sorting for them. The downside is having an additional request...

Beside of that I noticed that your response is not complaint with JSON:API. For resource linkage a resource identifier object (has-one) or a list of resource identifier objects (has-many) must be used.

You are using full resource objects. The difference is the attributes and links keys. Linked resource objects may be included in the response using a compound document.

Your idea using a query param to allow the client to control the inclusion of related resources is actually part of the spec. It uses the include query parameter therefore. This is described in detail in Inclusion of Related Resources chapter of the spec. But as said before that does not cover pagination and sorting of the included ressources.

jelhan
  • 6,149
  • 1
  • 19
  • 35
0

For anyone else who found @jelhan response helpful which I did, I found additional information from another json schema https://github.com/cloudcreativity/laravel-json-api/blob/develop/docs/basics/schemas.md#data

The abstract i found helpful

We do not recommend using data for any to-many relationships that could have a large number of related resources. For example, if our posts resource has a comments relationship, it would not be sensible to return data for the related comments because a post could have hundreds of comments. This would result in very slow encoding speed. Large to-many relations are best represented using links.

Also found in the documentation talks about to-many relationships https://jsonapi.org/format/#document-resource-object-relationships

A relationship object that represents a to-many relationship MAY also contain pagination links under the links member, as described below. Any pagination links in a relationship object MUST paginate the relationship data, not the related resources.

Martin Naughton
  • 1,476
  • 17
  • 14