As I understand it, a value object refers to how two objects are compared by executing code. If the client treats two objects as being equal if (and only if) those two objects have the same fields, then it’s comparing them by value (rather than by whether they reference the same memory location). But, I’m pretty sure that this compare-by-value semantic only exists on the client; I’m not sure why it’d be something that the server needs to signal.
Therefore, unless I’m missing some requirement, I’d suggest just making the lines
each their own resource (with an id
), after which it will be easy to include them when a sale is requested (the server can do so by default) and for each line item to link to the corresponding product. Then, if your client still wants to compare the line items by value, it can just ignore the "id"
.
So you’re response would look like this:
GET /sales
{
"data": [{
"id": "sale1",
"type": "sale",
"attributes": {
"date": "2015-10-12"
},
"relationships": {
"lines": {
"data": [{"type": "line-item", "id": "1"}, /* .... */ ]
}
}
}, {
//...
}],
"included": [{
"type": "line-item",
"id": "1",
"attributes": {
"price": 20.5,
"quantity": 5
},
"relationships": {
"product": {
"data": {"type": "product", "id": "product32"}
}
}
}]
}
Note that, above, the server has included the line items by default (which it’s allowed to do), without the client having to request them with the ?include=
parameter.
By the way, having the id above actually turns out to be quite helpful for allowing the client to update a given line item. That is, if your client wants to update a single line item on a given sale, it can just do PATCH /line-items/xxxxx
. If a line item didn’t have an id, it would have to either replace all the line items on the sale (PATCH /sales/sale1
with new lines
in the body), or reference the old line item it’s trying to PATCH by it’s index in the lines
array—but the latter approach isn’t reliable in a distributed environment, as a different client could have removed a line-item or reordered an item. So the id-based approach ends up being more robust.
If you don’t want clients to be able to retrieve a line-item independently from the sale it’s associated with, simply don’t support GET /line-items
and GET /line-items/xxxx
—there’s nothing in the spec that says you have to.
Does that work? Or am I missing something?