Constructing links to fetch resources seems non-RESTful


#1

Caveat: I’m new to “proper” RESTful design, so this question may be naive:

In the example, GETting “/articles/1” we see the response:

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


> }]
> }

For this question, let’s ignore the “included” section (as in the case where “included=” is not part of the query). This means, I believe, that to fetch just one of the comment resources directly, e.g. ({ “type”: “comments”, “id”: “12” }), you would either

(A) concatenate the “type” and “id” from the relationships.comments.data[0] item and issue a “GET /comments/12”

or

(b) concatenate the URI from releationships.comments.links.related and the relationships.comments/data[0].id and issue “GET /articles/1/comment/12”

Is one of those incorrect, are are both options available?

And, perhaps more to the meat of my question: Isn’t constructing a URL like this non-RESTful? It seems more RESTful (if more wordy) to include the exact URL in the relationships section, e.g. I’m proposing:

 >       "comments": {
>         "links": {
>           "self": "http://example.com/articles/1/relationships/comments",
>           "related": [
>             "http://example.com/articles/1/comments/5",
>             "http://example.com/articles/1/comments/12" 
>         ]
>       }

Thanks in advance for feedback / comments,

Mark


#2

New to this, but read the spec several times as implementing server side Perl.

Neither. Why? Because of absence of those links in the document.

In ideal world:

  • you ask article resource object with comments included
  • you go to “related” link to get collection of comments resourse objects
  • you provide meta information on how to get comments one by one, so extending spec

In real world you do (A) or © - go to /comments/ with list of ids of comments you don’t have in your local objects cache.

May be I’m totally wrong, but as far as I know naming conventions for paths of resources is not part of the spec.


#3

Hi Ruz,
I agree that I don’t see naming conventions for paths of resources in the spec. That is what confuses me with the examples that the Spec (1.0) provides.

In the above example, I’m trying to identify the components defined in the spec:
(1) the “Relationships object” - I think there are two of them, “author” and “comments”
(2) within the “comments” Relationship Object, the “Resource Linkage objects”, e.g. {“type”: “comments”, “id”: “12”}

Unfortunately, I can’t see where the Spec sets out how to use these two example objects and access the desired document.


#4

Yes, to be clear, the spec has no requirement on your URL space. We do have recomendations though, which are optional to follow:


#5

@steveklabnik - Let my try and re-focus my question: the documentation for “relationship object” says it MAY include a “data” member containing a “Resource Linkage”. Then, under the description of “Resource Linkage”, the spec talks about “Resource linkage in a compound document…”. Do I infer from this wording that the “data: {Resource Linkage” ONLY applies in the context of a compound document?


#6

@marklaff You’re right that constructing links is non-RESTful, and that the point of linkage isn’t for clients to construct links (it’s just for use with compound documents).

The link you’re looking for, to get an individual related comment, has been proposed but hasn’t been added yet. For now, the best substitute is to use the URI in the "related" link, which gives all the related comments. (If that’d be too many comments, though, that response can be paginated.) The reason the other link hasn’t been added yet is because, usually, the "related" link is sufficient. Still, we’re working on it.

For background, see https://github.com/json-api/json-api/issues/477 and https://github.com/json-api/json-api/issues/913


#7

@ethanresnick Ok, thanks. That resolves my mis-understanding. Can the “related:” object be a list, or must it be a URI (String)?

And, by way of feedback, the previous example, “Here’s how an article (i.e. a resource of type “articles”) might appear in a document:”, includes the same linkage content, “relationships.author.data” and doesn’t mention being a compound document, so one could draw the conclusion that the linkage would applicable to non-compound documents.

I suggest, while you are working on the updating this example to reflect your suggestion to represent relationships in the case when the linked entities are not included (i.e. non-compound case).

Thanks again to all for the great work, and for the discussion here.


#8

Currently, it has to be a string. I’m all in favor of allowing it to be sent as a list for pragmatic reasons (i.e. to unify the processing rules with those for upcoming links that will accept a list), but from a semantic point of view, I’m not sure how having multiple "related" links would make sense. The JSON API meaning of the related link (specialized from the IANA relation meaning) is “the set of resources that are part of the relationship”, and there’s really only one such set.

Fair enough. I’ll add cleaning up that example to my to do list. I’d also accept a PR that does so, if you’re up for writing one. (If so, though, keep in mind that linkage, perhaps unfortunately, isn’t explicitly prohibited in the non-compound document case; it’s just not designed or recommended for that case.)