-
Notifications
You must be signed in to change notification settings - Fork 890
Description
The use case
Consider the following cases:
- A resource representing a product has a
"price"
attribute, which is an object of the form:{"amount": ..., "currency": ...}
, where the"currency"
property refers to a particularcurrencies
resource. - A resource representing a project has a
"team-members"
attribute, which is an array of objects of the form:{"person": ...., "role-played": ...}
, where the"person"
and"role-played"
properties refer to particularpeople
androles
resources.
In both of the cases above, the attribute mentioned is an object or an array of objects that includes a link to another resource. But, crucially, the values for these attributes are only likely to occur in, or are only relevant in the context of, one resource. That is the (amount, currency) pair that represents a product's price doesn't make sense outside the context of that product, and the (person, role) pair that describes the role of a person on a particular project likely does not need to be considered outside of that project.
Accordingly, there's little semantic or functional justification for making separate, addressable resources from these "complex attributes"'s values. Meanwhile, turning them into separate resources can have a performance cost for backends implemented with document databases, which allow the complex attributes' values to be stored directly in the main resource's document. Therefore, the JSON-API spec shouldn't mandate that these complex attributes be turned into separate resources. But, if it's not going to mandate that, it has to somehow allow these complex attributes' links to other resources to be expressed in the response.
Prior Discussions
This issue has been discussed many times before, including in #238, #276, and #311. But many of the proposed solutions no longer apply post rc2. Post rc2, though, @bintoro made two proposals that offer good starting points for discussion.
My initial preferred approach
As I said previously, I think @bintoro's first proposal makes the a lot of sense. It's syntactically consistent with the current approach, and it seems easier to implement server-side than splitting up the complex attribute would be. Its downside, of course, is that it makes a parser's search for "links"
somewhat more complicated.
An in between option, that keeps it reasonably simple to find links but still keeps a complex attribute's value together, could be the following:
{
“data”: {
“id”: “1”,
“type”: “people”,
“name”: “Victor Mayonnaise”,
“links”: [“employer”, “address.city”],
“employer”: {
“relationship”: “http://example.com/people/1/links/employer”,
“resource”: “http://example.com/companies/2”
“type”: “companies”,
“id”: “2”
},
“address”: {
“street”: “12 Mean Street”,
“city”: {
“type”: “cities”,
“id”: “123”
}
}
}
}
Here, the link objects have been treated just like any other attribute value, so links out from simple attributes are now at the top-level the resource. The "links"
key just lists an array of paths that hold link objects.
I have a feeling this might get strong pushback, though, as people seem to like the idea of the "links"
key holding an object. I like that too, in theory, but I wonder whether, if the alternative is having multiple "links"
keys throughout the resource, the above isn't a better compromise. I don't know.
Thoughts?