Description
I used JSON:API back around 2016, when it had the bulk extension. I allowed attributes in relationships for create/update requests, and it worked great, I got a lot of work done. I can't remember if relationship attributes were allowed then, or if the spec was still evolving, or if I just missed that they weren't allowed.
Fast forward to 2023, and it appears that relationship attributes might not be allowed by the spec:
https://jsonapi.org/format/#crud-creating
https://jsonapi.org/format/#crud-updating
https://jsonapi.org/format/#crud-updating-resource-relationships
https://discuss.jsonapi.org/t/create-update-relationships-with-attributes/1701
So a simple request like this might not meet the spec:
# POST /posts
# comments would be at /posts/{post_id}/comments/{comment_id}
{
"data": {
"type": "posts",
"attributes": {
"title": "My title",
"content": "My content"
},
"relationships": {
"comments": [
{
"data": {
"type": "comments",
"attributes": {
"content": "My comment"
}
}
}
]
}
}
}
Evidently we're supposed to create comments separately in previous requests and only have {"type": "comments", "id": "{id}"}
in relationships?
I realize that typically we wouldn't create posts and comments simultaneously. But I could have just as easily chosen tags, categories or users to invite (by an email attribute if they don't have an account yet). If I read the current spec correctly, it bars the simplest use-cases like that.
I'd like to hear a nonidiological answer as to why we can't create/update resources with attributes and even a hierarchy of relationships. The only thing I can think of is that JSON:API might not always support including resources beyond one layer well. But that's not really a technical issue, it's a design decision.
You're competing with stuff like GraphQL and Firebase that lets us perform bulk atomic operations, so I have to be honest, the new atomic operations extension stuff appears to have jumped the shark. You're asking frontend developers to concern themselves with implementation details like atomicity/transactions, rather than the use-cases of the user stories they need to implement. In other words, you might be making their job harder without justification.
I'm probably going to only loosely adhere to the spec and allow attributes and maybe even relationships in included resources. The PHP League's Fractal package attempted to partly address that with its syntax to provide extra parameters in its include method, formatted like ?include=comments:limit(5|1):order(created_at|desc)
, under the Include Parameters
section at https://fractal.thephpleague.com/transformers/ and that approach could certainly be extended to filter included items like comments.author.likes:limit(5|1)..
(for example) at any level. A more thorough implementation can be found at https://laraveljsonapi.io/docs/3.0/routing/writing-actions.html and https://laraveljsonapi.io/docs/3.0/requests/query-parameters.html although they don't mention attributes in relationships. I really hope that I just missed something and that someone can demonstrate how to do my above example in a single simple request.
Edit: I had quite a workday yesterday, so revised this to remove any harshness from my tone! Also I found a previous thread which summarizes many of my concerns:
This answer aligns most with how I originally envisioned JSON:API working:
Rereading the spec, I don't see a ban on having relationships.*.data.attributes
for POST/PATCH requests, so I'm going to proceed with using them until I hear a good reason not to.