json-api-serializer icon indicating copy to clipboard operation
json-api-serializer copied to clipboard

Support for relationship data serialization?

Open ckeboss opened this issue 5 years ago • 2 comments

The JSON:API spec defines relationships links such as:

GET /articles/1/relationships/tags

HTTP/1.1 200 OK
Content-Type: application/vnd.api+json

{
  "links": {
    "self": "/articles/1/relationships/tags",
    "related": "/articles/1/tags"
  },
  "data": [
    { "type": "tags", "id": "2" },
    { "type": "tags", "id": "3" }
  ]
}

Currently, there is no way to serialize tags, as if you serialize it with attributes, you will get:

  "links": {
    "self": "/articles/1/relationships/tags",
    "related": "/articles/1/tags"
  },
  "data": [
    { "type": "tags", "id": "2", "attributes": { "name": "foo" } },
    { "type": "tags", "id": "3", "attributes": { "name": "bar" } },
  ]
}

Which violates the spec:

The primary data in the response document MUST match the appropriate value for resource linkage, as described above for relationship objects.

Resource linkage in a compound document allows a client to link together all of the included resource objects without having to GET any URLs via links.

Resource linkage MUST be represented as one of the following:

null for empty to-one relationships. an empty array ([]) for empty to-many relationships. a single resource identifier object for non-empty to-one relationships. an array of resource identifier objects for non-empty to-many relationships.

You can somewhat get around this by simply not passing any additional data other than id to the serializer, but you will still get an empty object on the attributes property. The downside to this is that if you want to actually include the data, you are allowed to, but within the includes property, as defined here:

Furthermore, related resources can be requested from a relationship endpoint:

GET /articles/1/relationships/comments?include=comments.author HTTP/1.1
Accept: application/vnd.api+json

In this case, the primary data would be a collection of resource identifier objects that represent linkage to comments for an article, while the full comments and comment authors would be returned as included data.

I think there needs to be a boolean on the serialize method to identify if you are serializing a relationship or not.

Thoughts?

ckeboss avatar Dec 17 '19 23:12 ckeboss

Yes, you can't actually directly serialize relationship data.

Maybe you can get around this by serializing primary data and picking relationship data and includes from the result. The idea of ​​a boolean on the serialize method should work, but in my opinion, the method is starting to have a lot of arguments...

Wouldn't it be better to have a new method serializeRelationship ?

danivek avatar Dec 19 '19 10:12 danivek

Yes, I think a different method would be better

ckeboss avatar Dec 19 '19 15:12 ckeboss

I have developed a full-featured library in typescript for simply serializing JSON:API. It serializes the entire spec. It can serialize relationships particularly well.

Link: https://github.com/jun-sheaf/ts-japi

jrandolf avatar May 20 '20 17:05 jrandolf