Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create/update relationships having attributes? #1705

Open
zmorris opened this issue Jun 23, 2023 · 3 comments
Open

Create/update relationships having attributes? #1705

zmorris opened this issue Jun 23, 2023 · 3 comments
Labels
extension Related to existing and proposed extensions as well as extensions in general

Comments

@zmorris
Copy link

zmorris commented Jun 23, 2023

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:

#1089

This answer aligns most with how I originally envisioned JSON:API working:

#1089 (comment)

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.

@zmorris zmorris changed the title Why can't we create/update relationships having attributes? Create/update relationships having attributes? Jun 24, 2023
@lode
Copy link
Contributor

lode commented Jul 1, 2023

First on the formal part.

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.

On creating resources it states:

If a relationship is provided in the relationships member of the resource object, its value MUST be a relationship object with a data member. The value of this key represents the linkage the new resource is to have.

Where linkage is zero or more resource identifier objects which only allow type, id, lid and meta.

On updating resources this isn't mentioned as explicit. But on updating relationships it is mentioned again that resource identifier objects should be used.


Further I feel your pain. It would be really handy if creating resource and its relationship could be done in one go.

I now often include an attribute on the primary resource which then would be passed on to the resource of the relationship:

{
	"data": {
		"type": "posts",
		"attributes": { 
			"title": "Some title",
			"tagNames": [
				"foo", "bar"
			]
		}
	}
}

I think the current alternative, next to the atomic extension, is to have multiple calls. I don't think that approach is very weird, but I also notice I often find myself being lazy to create that other endpoint which I wouldn't need otherwise.

@jelhan
Copy link
Contributor

jelhan commented Jul 1, 2023

If the Atomic Operations extension feels overly complex and your use care requires creation of resources only (not updating or deleting resources), the Bulk Create extension might be a good fit. It allows creation of multiple resources in a single, atomic request using a JSON:API document similar to compound documents.

@jelhan jelhan added the extension Related to existing and proposed extensions as well as extensions in general label Jul 1, 2023
@FranzDeschler
Copy link

Version 1.1 of the specification now allows adding specification semantics via extensions.
So from my understanding, you can define your own extension which extends the "data" object accordingly by the required fields.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
extension Related to existing and proposed extensions as well as extensions in general
Projects
None yet
Development

No branches or pull requests

5 participants
@lode @zmorris @jelhan @FranzDeschler and others