How to use sparse field sets for meta, links and relationships


#1

For the given resource:

{
  "links": {
    "self": "http://example.com/articles",
    "next": "http://example.com/articles?page[offset]=2",
    "last": "http://example.com/articles?page[offset]=10"
  },
  "data": [{
    "type": "articles",
    "id": "1",
    "attributes": {
      "title": "JSON API paints my bikeshed!",
      "rating": 5,
      "createdAt": "2018-01-05 10:55"
    },
    "meta": {
         "numberOfViews": 25,
         "copyright": "2018 (c) All rights Reserved"
     },
    "relationships": {
      "author": {
        "links": {
          "self": "http://example.com/articles/1/relationships/author",
          "related": "http://example.com/articles/1/author"
        },
        "data": { "type": "people", "id": "9" }
      },
      "publisher": {
        "links": {
          "self": "http://example.com/articles/1/relationships/publisher",
          "related": "http://example.com/articles/1/publisher"
        },
        "data": { "type": "publishers", "id": "10" }
       }
      "comments": {
        "links": {
          "self": "http://example.com/articles/1/relationships/comments",
          "related": "http://example.com/articles/1/comments"
        },
        "data": [
          { "type": "comments", "id": "5" },
          { "type": "comments", "id": "12" }
        ]
      }
    },
    "links": {
      "self": "http://example.com/articles/1"
    }
  }],
  "included": [{
    "type": "people",
    "id": "9",
    "attributes": {
      "first-name": "Dan",
      "last-name": "Gebhardt",
      "twitter": "dgeb"
    },
    "links": {
      "self": "http://example.com/people/9"
    }
  }, {
    "type": "comments",
    "id": "5",
    "attributes": {
      "body": "First!"
    },
    "relationships": {
      "author": {
        "data": { "type": "people", "id": "2" }
      }
    },
    "links": {
      "self": "http://example.com/comments/5"
    }
  }]
}

We can use sparse fieldsets to choose the fields attributes we want returned, like so:

fields[offer]=title,rating

However, how can we use sparse fieldsets to choose other data, such as:

  • meta data. e.g. only numberOfViews
  • relationships e.g. perhaps you only want to show the author, but not the comments. You might also not want to include the links.
  • links at any level. e.g. you might not want to include the links at the root, or relationship links.
  • type or id

I have come up with 3 solutions:

Solution 1
We can extend the spec to accept more options like so:

rootFields[offer]=id
fields[offer]=title,rating
metaFields[offer]=numberOfViews   
relationshipFields[offer]=author,publishers.data.id
links[offer]=                       // Doesn't return anything for any offer links

This also has the advantage of using default values if the parameter is missing. For example, not adding rootFields[offer] will mean type and id is always included.

Solution 2
Change the spec slightly like so:

fields[offer][root]=id
fields[offer][attributes]=title,rating
fields[offer][meta]=numberOfViews   
fields[offer][relationships]=author,publishers.data.id
fields[offer][links]=                // Doesn't return anything for any offer links

This also has the advantage of using default values if the parameter is missing. For example, not adding fields[offer][root] will mean type and id is always included.

But I think this may be a breaking change from the the specification, which I don’t really want to do.

Solution 3
Allow values in fields that are not attributes. e.g.

fields[offer]=root.id,title,rating,numberOfViews,relationships.author,relationships.publishers.data.id

Unfortunately, this means I cannot use default values.

Is there a better solution (preferably something that is compliant with the spec)?
Does the above 2 solutions seem suitable. If so which is better?