GET /articles/1/relationships/comments and a GET /articles/1/comments

I’m a little confused about the difference between doing a GET /articles/1/relationships/comments and a GET /articles/1/comments Do both do the same thing? What’s the difference and what does the result json look like.

Cam, I recently explained this in a different but similar thread.

Go ahead and take a look at this post as a summary, the entire thread I think will be useful for context.

I did see that post earlier and it seemed to help a little, but I’m still not sure what the difference is and if using one over another is correct or incorrect.

It did help that there is a difference between people and author. However, I’m still confused and trying to understand the api spec.

In the scenario of comments, there would be a description, title, person, and article. An article could how many comments.

So if you made GET /articles/1/comments, what would the contents of the results be
{
“data”: [
{
“attributes”: {
“person_id”: “53b2162d19394227b56d5cdca5c3dc9f”,
“desc”: “Another Test”
},
“type”: “comments”,
“id”: “b32bf65b6715419992c703a6e671d263”
},
{
“attributes”: {
“person_id”: “53b2162d19394227b56d5cdca5c3dc9f”,
“desc”: “Cams - Test”
},
“type”: “comments”,
“id”: “84e759fe232d427db90417624718ee4b”
}
],
“links”: {
“self”: “http://api.test.dev/articles/1/comments
}
}

Is that correct, or would the url be /articles/1/relationsips/comments to return the above result or am I way off. Thank you for your assistance.

It’s relatively easy to understand when you get your head around it. Until then, it’s not obvious at all I found.

There are three types of URLs in JSON-API.

  • Resource URLs. This is - for example - “/articles/1”
  • Related Resource URLs. This is - for example - “/articles/1/author”
  • Relationship URLs. This is - for example - “/articles/1/relationships/author”

The “Resource URL” is a direct URL to a resource, or collection of resources.

The “Related Resource URL” is a stable URL to a resource related to another one. This confused me a lot to start with. As an example here, if the current author of Article 1 is Person 3 then “/articles/1/author” will return the same as “/people/3”. If the current author of Article 1 were to somehow be changed to Person 5 then “/articles/1/author” will still return the current author of Article 1, but this will now be the same as “/people/5” instead.

This means that you can always rely on “/articles/1/author” to return the current author of Article 1, whichever resource that is. It’s a case of having stable URLs that point to different data, instead of the URL itself changing when the data changes.

The “Relationship URL” is going to return information about the Relationship between two resources, instead of the Related Resource itself. Unfortunately the fact that a Relationship can not have any data of it’s own limits the usefulness of this, but it still has some benefit.

As a worked example:

  • GET /articles/1 - This will return Article #1
  • GET /articles/1/author - This will return Person #3
  • GET /articles/1/relationships/author - This will return the following:
    {
      "links": {
        "self": "/articles/1/relationships/author",
        "related": "/articles/1/author"
      },
      "data": {
        "type": "people",
        "id": "3"
      }
    }

Literally just the details of the relationship between Article #1 and it’s Author - Person #3.

The real benefit of this is when you want to edit them. You can do a PUT /articles/1/relationships/author with the details of the new author, or (Bad example here) a DELETE /articles/1/relationships/author to delete the Relationship between the two. This does not delete the Person record, just the connection between the Article and the Person.

1 Like

I believe that answers my question and clears up how it works. Thank you very much.

Let’s say there were two comments on article 1. Is the following valid and if so, what would the results look like:

GET /articles/1/relationships/comments

Thank you for your help.

I think I found the answer. A GET request to a URL from a to-many relationship link could return:

{
“links”: {
“self”: “/articles/1/relationships/comments”,
“related”: “/articles/1/comments”
},
“data”: [
{ “type”: “comments”, “id”: “2” },
{ “type”: “comments”, “id”: “3” }
]
}

Either that, or else you could choose not to return the data at all if you wish. That would be the case when it’s expensive to determine what they all are.

From the spec: (Emphasis mine)

A “relationship object” MUST contain at least one of the following:
links
data
meta

So you would be perfectly justified in returning the links, and possibly a meta object with the size of the collection but not actually return the IDs of the records in the collection.

Thank you. I did see that, but didn’t think about making the data optional. Very good point and will keep that in mind. Thanks again everyone.

Correct, but I’m obligated to continue making the statement that comments shouldn’t be a sub-resource in the example, and the related URI should point to the canonical URL for the resource /comments.

Representing the comments as a sub-resource along with hypermedia is the very cause of most of this confusion.

Can you give an example of what you mean?

My previously linked post to the other thread contains the very explanation you want.

By including an non-dependent resource as a sub resource, the example blurs the line on the difference between /resource/{id}/relationships/{rel-name} and the related link.

Being within a hierarchy is another form of relationship, therefor the distinction between:

"self":"/articles/33/relationships/comments"
"related":"/articles/33/comments"

and

"self":"/articles/33/relationships/comments"
"related":"/comments?filter[article]=33"

is conflated in many explanations. They oversimplified the example to the point where it became ambiguous and unclear. The related link should be the canonical, meaning will not change, link to retrieve the set of related resources.

Thank you for the detailed information. Very much appreciated.