beam-community/jsonapi

Empty one-to-one relationship incorrectly surfaced (should be surfaced as null)

theirishpenguin opened this issue · 6 comments

Currently, if there is a one-to-one relationship and it is empty the related resources key gets removed from the "relationships" object. But, according to https://jsonapi.org/format/#document-resource-object-linkage this should not happen...

"Resource linkage MUST be represented as [...] null for empty to-one relationships."

Rather, the relationship data should be set to null - there is an example at https://stackoverflow.com/a/57414080

Here is an example...

{
    "type": "articles",
    "id": "1",
    "attributes": {
      "title": "JSON:API paints my bikeshed!"
    },
    "relationships": {
      "author": {
        "links": {
          "self": "http://example.com/articles/1/relationships/author",
          "related": "http://example.com/articles/1/author"
        },
        "data": { "type": "people", "id": "9" }
      },
      ...

Expected Result

If author is null, we should get...

{
    "type": "articles",
    "id": "1",
    "attributes": {
      "title": "JSON:API paints my bikeshed!"
    },
    "relationships": {
      "author": {
        "data": null
      },
     ...

Actual Result

But if author is null, we actually get...

{
    "type": "articles",
    "id": "1",
    "attributes": {
      "title": "JSON:API paints my bikeshed!"
    },
    "relationships": {
   }
      ...

No author relationship.

I've created a PR to workaround (maybe even solve or partially solve?) this issue at #278

I've annotated the code at https://github.com/beam-community/jsonapi/pull/278/files for a clearer explanation.

The key moment in the code is here where we can cleanly surface a nil without many code changes.

Outstanding Work

If this approach bears fruit then we need to

  • Remove null relationship resources from the includes section as well
  • Add tests

My reading of the JSON:API specification has always left this as an implementation detail. In my reading, a relationships object (plural) must contain keys which are each valid relationship objects but it is not required to contain the same keys for every request for a certain resource. Therefore, a to-one relation that does not exist (may be null in some backend or database) can either be omitted entirely from the relationships object or else it must be serialized properly as a relationship object which is to say it is {"data": null}.

In my opinion, it is nonetheless unfortunate for a library to pick one or the other because I actually feel there's a useful distinction between omitting and nulling out in an API contract and both should be possible depending on the API.

At any rate, I would call this a feature request more than a bug based on my understanding of the specification.

Hi @mattpolzin, thanks for the quick reply. I haven't internalised the JSON:API specification in detail in this area - your reading of it sounds reasonable to me and I am happy to yield to that interpretation :-) I agree that supporting both would be ideal if that is what the spec allows. So I'd be in agreement with your above suggestions.

This issue has been automatically marked as "stale:discard". We are sorry that we haven't been able to prioritize it yet.
If this issue still relevant, please leave any comment if you have any new additional information that helps to solve this issue. We encourage you to create a pull request, if you can. We are happy to help you with that.