Will
Will

Reputation: 1551

JSON API automatic reverse links

Is it a violation of the JSON-API spec to allow reverse relationships to be created automatically?

I need to create resources that, when I link A to B in a relationship, automatically links B to A. In this way I can traverse A to find all of its Bs and can find the parent A from a B. However, I don't want to POST/PATCH to 2 relationships to get this right. I want to establish the relationship once.

Now I know that it is an implementation detail as to how the server maintains link/references as well as how the behaviour is established but I want to build the API in such a way that it doesn't violate the spec.

Assuming I have resources Books and Authors. Books have Authors and Authors have Books. The question is, once I relate an Author to a Book, I need the reverse relationship to be created as well. Is it a violation of the spec in any way to assume that this reverse relationship can be automatically created by simply doing one POST to the Books resource's relationship?

By way of example, starting with the book.

{
    "data": {
        "type": "books", "id": 123, "attributes": ...,
        "links": { "self": "/books/123" },
        "relationships": {
            "self": "/books/123/relationships/authors",
            "related": "/books/123/authors"
        }
     }
}        

And the author

{
    "data": {
        "type": "authors", "id": 456, "attributes": ...,
        "links": { "self": "/authors/456" },
        "relationships": {
            "self": "/authors/456/relationships/books",
            "related": "/authors/456/books"
        }
     }
}        

If I establish the link from a book to an author with a POST to /books/123/relationships/authors

{
    "data": [{ "data": "authors", "id": "456" }]
}

Do I need to explicitly do the same for the Author 456 as a POST to /authors/456/relationships/books?

{
    "data": [{ "data": "books", "id": "123" }]
}

Or can I let the server build the relationship for me so that I can avoid the second POST and just see the automatic reverse relationship at GET /authors/456/relationships/books?

Upvotes: 0

Views: 144

Answers (1)

jelhan
jelhan

Reputation: 6338

From the perspective of the spec this is only one relationship represented from two different sides. author and book have a many-to-many relationship. This relationship could be represented in author's resource object as well as book's resource object and of course also via there relationship links. Actually it would be a violation of the spirit of the specification if representations wouldn't match. Having one-sided relationships is another story but in that case one side wouldn't know about the relationships at all (e.g. a book is associated with an author but the author model does not know which books are associated with it).

A post to either one side of that relationship creates the relationship between the two records. It shouldn't matter which side is used to create that relationship and if it's created as part of a creation / update to a resource via it's resource object or via a relationship link representing that relationship. The same applies to deletion of that relationship.

Maybe an example would make that even more clear. Let's assume a book is created with a POST to /books?include=author having these payload:

{
  "data": {
    "type": "books",
    "relationships": {
      "author": {
        "data": {
          "type": "authors",
          "id": "1"
        }
      }
    }
  }
}

The response may look like this:

{
  "data": {
    "type": "books",
    "id": "7",
    "relationships": {
      "author": {
        "data": { "type": "authors", "id": "1" }
      }
    }
  },
  "included": [
    {
      "type": "authors",
      "id": "1",
      "relationships": {
        "books": {
          "data": [
            { "type": "books", "id": "7" }
          ]
        }
      }
    }
  ]
}

Upvotes: 1

Related Questions