-
Notifications
You must be signed in to change notification settings - Fork 890
Description
JSON API currently does not implement Web Linking. More specific, it does not implement relations according to the RFC.
Judging from a Twitter discussion on Sunday, this might be intentional rather than by accident.
RFC 5988 divides into two kinds of relations types: Registered and extension types. I think the main reason this was not used is because extension types are supposed to be URIs (which are not meant to be dereferenced).
However:
Note that while extension relation types are required to be URIs, a serialisation of links can specify that they are expressed in another form, as long as they can be converted to URIs.
Why is this bad?
- The server cannot rely on general purpose clients inferring semantics from well defined, registered relation types, like "next". A side effect of this is that a "profile" meta attribute had to be added, which could have otherwise been just a link.
- It is not possible to properly use extension types, making integration with other API standards, like json-home a bit more problematic.
Possible solutions
Not fixing this
{
"posts": [{
"id": "1",
"title": "Rails is Omakase",
"links": {
"author": "http://example.com/people/17",
"comments": "http://example.com/comments/1"
}
}]
}
You could assume the standpoint that generic implementations of pagination and integration with json-home are not worth it, or not feasible and that a mapping from relation types to JSON API links should happen in the documentation, if at all.
Fully implementing it
This would probably be the most radical approach and break compatibility with existing implementations.
An example of what this would look like:
{
"posts": [{
"id": "1",
"title": "Rails is Omakase",
"links": {
"author": "http://example.com/people/17",
"http://example.com/rel/comments": "http://example.com/comments/1"
}
}]
}
Or with a well defined shorthand (inspired by HAL):
{
"links": {
"curies": {
"ex": "http://example.com/rel/{rel}",
"acme": "http://docs.acme.com/relations/{rel}",
}
},
"posts": [{
"id": "1",
"title": "Rails is Omakase",
"links": {
"author": "http://example.com/people/17",
"ex:comments": "http://example.com/comments/1"
}
}]
}
To simplify this, the :
prefix could be defined as ://{host}/relations/{rel}
implicitly:
{
"posts": [{
"id": "1",
"title": "Rails is Omakase",
"links": {
"author": "http://example.com/people/17",
":comments": "http://example.com/comments/1"
}
}]
}
Even if it wouldn't break compatibility, I'm not sure I would like this approach (and I really mean not sure, not that I don't).
Making the rel
attribute part of the spec
Simple, and makes it opt-in.
{
"posts": [{
"id": "1",
"title": "Rails is Omakase",
"links": {
"author": {
"href": "http://example.com/people/17",
"rel": "author"
},
"comments": {
"href": "http://example.com/comments/1",
"rel": "http://example.com/comments/1"
}
}
}]
}
This again would work with curies and would also allow choosing to set a relation type on a per link basis:
{
"posts": [{
"id": "1",
"title": "Rails is Omakase",
"links": {
"author": {
"href": "http://example.com/people/17",
"rel": "author"
},
"comments": "http://example.com/comments/1"
}
}]
}
I think to be able to use this, it would need to be part of the spec, even though just adding the rel attribute might not violate the current spec. But without it being part of the spec, there would be little to no incentive for library/framework developers to implement this feature.
What I don't like about this approach is that in all the examples I can think of the relation type and the relation name would pretty much be identical (as author is above).
The implicit rel
attribute
{
"posts": [{
"id": "1",
"title": "Rails is Omakase",
"links": {
"author": "http://example.com/people/17",
"comments": "http://example.com/comments/1"
}
}]
}
This would basically be a hybrid of the above:
- Allow defining curies in the links section.
- Allow adding
rel
attribute explicitly to links. - If
rel
is not explicitly set and the relation name corresponds to a known relation type, assume therel
attribute equals the relation name. - Optional: If the relation name does not correspond to any known relation type, and the
rel
attribute is not explicitly set, assume://{host}/relations/{rel}
(thus all links would conform with RFC 5988).
The only real downside I can see is that people might accidentally use a relation type that doesn't fit ("Oh, I called it author, even though it doesn't refer to the context's author. Didn't know that was implied"). I feel like that's an acceptable tradeoff if this logic is part of the spec.
Conclusion
If you think any of this is valid and this issue reaches some consensus, I'd be more than willing to submit a pull request.