json-api-dotnet / JsonApiDotNetCore

A framework for building JSON:API compliant REST APIs using ASP.NET and Entity Framework Core.

Home Page:https://www.jsonapi.net

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Client-generated IDs doc should mention 204

verdie-g opened this issue · comments

The fact that

POST /authors
Content-Type: application/vnd.api+json

{
  "data": {
    "type": "authors",
    "attributes": {
      "name": "toto"
    }
  }
}

returns 201 with the created resource but

POST /authors
Content-Type: application/vnd.api+json

{
  "data": {
    "type": "authors",
    "id": "1234",
    "attributes": {
      "name": "toto"
    }
  }
}

can return 204 with no body is confusing.

I understand that you are following the spec https://jsonapi.org/format/#crud-creating-responses-204 so I think it deserves a big warning in the doc (https://www.jsonapi.net/usage/options.html#client-generated-ids). I would do it but I'm not sure in which exact case it returns 204.

This is how JSON:API works. It states only to send back data when side effects have occurred that the caller cannot know of. This applies to all write endpoints. It avoids pointless network traffic. We don't explain how JSON:API works in our docs, that's what the spec does. If you feel the spec is non-intuitive or wrong, please challenge the topic there.

This is actually documented at https://www.jsonapi.net/usage/writing/creating.html, so I'm closing this.

This is actually documented at https://www.jsonapi.net/usage/writing/creating.html

Indeed, I missed that one.

When using client-generated IDs and only attributes from the request have changed, the server returns 204 No Content

This is the first time I ever see that behavior in a REST API so even if this in the specification, I feel like this could be reworded to avoid any ambiguity.

The "only attributes from the request have changed" is confusing to me because the POST endpoint creates a resource so I'm not expect any change. I suppose the change here is between the request payload and the created resource. What do you think of just using what's in the spec? Something like

If the requested resource has been created successfully and the server does not change the resource in any way (for example, by assigning an id or createdAt attribute), the server returns either a 201 Created status code and response document or a 204 No Content status code with no response document.

The spec is written in formal language, not easily understood by end users. It is particularly vague regarding "relationship changes", causing recurring questions from implementors. So I certainly don't want to quote that.

But I agree our current wording can be clarified. How about this:

When using client-generated IDs and all attributes of the created resource are the same as in the request, the server returns 204 No Content. Otherwise, the server returns 201 Created, along with the stored attributes and its newly assigned ID.

Sounds good thanks. The same sentence is also in the patch documentation. I PR or you do?

The description from https://www.jsonapi.net/usage/writing/updating.html looks clear to me, don't you agree?

When only the attributes that were sent in the request have changed, the server returns 204 No Content. But if additional attributes have changed (for example, by a database trigger or resource definition that refreshes the last-modified date) the server returns 200 OK, along with all attributes of the updated resource.

Agreed, it's great. I think we should also emphasize that all the fields should present to get a 204 in the POST. I suppose 204 can't be returned if one field doesn't have the AttrCapabilities.AllowCreate.

Agreed, it's great. I think we should also emphasize that all the fields should present to get a 204 in the POST. I suppose 204 can't be returned if one field doesn't have the AttrCapabilities.AllowCreate.

No, that's not true. Optional fields can be omitted in POST, as well as non-creatable ones (like CreatedAt, which could be assigned from a database trigger). So it's up to the server to assign a value (or not), possibly customized by the API developer. Only if that assigned value differs from the type's default value, you'd get the resource back. But I think that's a bit too much information to provide in this doc.

Ok, I've updated the PR with just your suggested wording.