Usage of `related` field in Relationships link


#1

Hi,
I would like to have a better understanding of the relationship link and in particular the related field.
I have clear that the self link regards the relationship itself but how I can use and interpret the related link?
For what I understand the related link could be constructed referring directly to the resource related.

An example could clear what I’m asking:
I have two resources: bands and musicians.
Considering that I can access to single object using bands/:id or musicians/:id what is the expected related link? I present two options for a possible response to a GET bands/1.
One

{
  "links": {
    "self": "http://example.com/bands/1"
  },
  "data": {
    "type": "bands",
    "id": "1",
    "attributes": {
      "title": "Slint"
    },
    "relationships": {
      "guitarist": {
        "links": {
          "self": "/bands/1/relationships/guitarist",
          "related": "http://example.com/bands/1/musicians"
        },
        "data": { "type": "musicians", "id": "9" }
      },
      "drummer": {
        "links": {
          "self": "/bands/1/relationships/drummer",
          "related": "http://example.com/bands/1/musicians"
        },
        "data": { "type": "musicians", "id": "11" }
      }
    }
  }
}

Two

{
  "links": {
    "self": "http://example.com/bands/1"
  },
  "data": {
    "type": "bands",
    "id": "1",
    "attributes": {
      "title": "Slint"
    },
    "relationships": {
      "guitarist": {
        "links": {
          "self": "/bands/1/relationships/guitarist",
          "related": "http://example.com/musicians"
        },
        "data": { "type": "musicians", "id": "9" }
      },
      "drummer": {
        "links": {
          "self": "/bands/1/relationships/drummer",
          "related": "http://example.com/musicians"
        },
        "data": { "type": "musicians", "id": "11" }
      }
    }
  }
}

Thank you for the eventual reply!


Creating/updating a resource AND its relationships
#2

Your first example is the right one. That is, the related link, when requested, should return the exact set of resources that are in the relationship. So, if the "guitarist" relationship of /bands/1 contains a single resource ({"type": "musicians", "id": "9"}), then the response from GETing the related link should contain the resource object for musician 9.


#3

Hi @ethanresnick thank you for your reply.
So I could use also something like this for the related link?

"relationships": {
      "guitarist": {
        "links": {
          "self": "/bands/1/relationships/guitarist",
          "related": "http://example.com/musicians/9"
        },
        "data": { "type": "musicians", "id": "9" }
      },

I added the ID for the single resource directly in the related link.
This could be a possible solution? Although I think that with this I have the problem for collection of resources (let’s say a list of related events/concerts).


#4

Unfortunately not. The content returned at the related link has to always reflect the current status of the relationship. That is, if a client requests /bands/1 and stores the related URI for the guitarist, it should be able to request the URI later and get the current guitarist (even if it’s no longer musician 9). If you don’t want to support that functionality on your server, you can simply omit the related link (which is entirely optional).


#5

Hi @ethanresnick thank your for the reply, that cleared some points.
Actually We are using emberJs client-side and, as it presents itself as a sort of exemplar implementation of JSON-API, We watched how it works when we omit the links object.
We saw that it inherits the link for the relationship basing on the resource type and the ID, so in our case the URL requested is /musicians/9.
What you suggest for a possible implementation is to add the related link to express the current status however can we consider the emberJs “expectations” as an indicator to how JSON-API intended the related field?

Thank you!


#6

When the "related" link is absent, Ember does its best to cope with that. It requests /musicians/9 because that’s the best guess it can make for how to fetch useful data. But just because this is what Ember falls back to when "related" is not present—again, as a “best guess”—that doesn’t change the meaning of the related when it is present, or imply anything about what was intended for that field. Ember is anexemplar implementation, but the spec ultimately exists beyond ember, so the specification text has the final say, and it’s clear on this point:

Additionally, a related resource link [i.e. the URL] MUST NOT change because its relationship’s content changes.


#7

Thanks for this thread, it definitely helps clear up some confusion I had - I had a quick question regarding the response from GET request to the related link.

In the first example above, as @ethanresnick mentioned, if the user makes the request:

GET /bands/1/relationships/drummer

At any point in time, the response should always include the resource object that represents the current drummer (or null, if the band has no drummer).

When representing that drummer, in the data attribute of the response document, is it fair to include a data.links.self attribute, that points to the direct link to that musician (based off of /musicians)?

A response like:

{
  "links": {
    "self": "http://examples.com/bands/1/relationships/drummer"
  }
  "data": {
    "type": "musicians",
    "id": "9",
    "attributes": {
      firstName: "Matt"
    },
    "links": {
      "self": "http://example.com/musicians/9"
    }
}

And if musicians also had another association, like, their “preferred” equipment, could those relationships be included as part of the document above, say under data.relationships?

My main point being - http://examples.com/bands/1/relationships/drummer is the end of the road (no more sub-nodes)… if the requestor wants to find more details related to this particular “current drummer”, they’ll start issuing requests based off of the http://example.com/musicians/9 resource. Is this correct thinking?

Thanks for your help!


Relationships level or basic rules joining related resourses
#8

Yes, absolutely! Your example, with the top-level "self" link pointing to http://examples.com/bands/1/relationships/drummer while the one at the resource object level (i.e., the one under "data") points to http://example.com/musicians/9, is exactly correct. And it’s a perfect demonstration of why both levels exist.

 

Definitely. The drummer represented is just a standard resource object, so it can certainly include relationships of its own. In fact, it should include those additional relationships if they exist (unless there’s a ?fields restriction). That way, users can just follow one relationship to the next, to the next, without ever having to go back and request /musicians/9 directly.

 

Just a brief aside: JSON API suggests using /bands/1/drummer as the "related" link, to save /bands/1/relationships/drummer for the "drummer" relationship’s "self" link, like so:

GET /bands/1

{
  "data": {
    "type": "bands", 
    "id": "1", 
    "attributes": { /* attributes */},
    "relationships": {
      "drummer": {
        "links": {
          "self": "http://example.com/bands/1/relationships/drummer",
          "related": "http://example.com/bands/1/drummer"  // no "/relationships/" by convention
        }
      },
      // other relationships
    }
  }
}

However, following this recommendation is absolutely not required. If you want to use http://example.com/bands/1/relationships/drummer as the "related" link, and make up something else for the "self" link (or not include one), that’s fine. A conforming client will use whatever strings the "self" and "related" keys hold. Still, following the convention can make your API seem a bit more familiar to developers who have worked with other JSON API backends.

Note: For a discussion of the differences between the "self" and "related" links of a relationship object, since I don’t think it came up in the earlier discussion, see here.


Relationships level or basic rules joining related resourses
#9

This is excellent validation, and thanks for pointing out the typo in my GET request. Thanks @ethanresnick!


#10

[quote=“ethanresnick, post:8, topic:145”]
Note: For a discussion of the differences between the “self” and “related” links of a relationship object, since I don’t think it came up in the earlier discussion, see here.[/quote]

Now I’m confused.
You say that the self link http://examples.com/bands/1/relationships/drummer can contain data like relationships, attributes and links.
However, in the link you provided Relation Link Usage it is said that this should not be included. Instead it should only be included resource identifier objects (only type and id.

What is correct now?

If your version is correct then self link and related link would more or less return the same content?