4

Given the following scenario:

  1. Teacher entity

    {  
    "id": "1234",  
    "name": "Mr. Didactic",  
    "Subject": "History",  
    "Classroom": "1A"  
    }
    
  2. REST API endpoint:

    /teacher/id/1234
    

Let's say I submit a POST (update) request to the endpoint with this request body:

{  
"id": "1234",  
"name": "Mr. Didactic",  
"Subject": "History"
}

How should that be handled/interpreted? Is Classroom being requested to be set to null/empty?

Or is it untouched, i.e. don't do anything to Classroom, it's not part of the request?

Or is there some other way of interpreting this? What's expected, or are the best practices here?

  • 1
    Did you confuse PUT and POST? POST doesn't really fit updates. – CodesInChaos Feb 11 '16 at 23:36
  • I'd treat it as empty for PUT and as unmodified for PATCH. – CodesInChaos Feb 11 '16 at 23:39
  • 1
    I think you want to use PATCH for partial updates. – NoobsArePeople2 Feb 11 '16 at 23:39
  • @CodesInChaos PUT is not for updates unless you are completely replacing the entity. – richard Feb 12 '16 at 0:14
  • 2
    @RichardDesLonde You can use POST but PATCH is explicitly meant for partial updates. Using PATCH would signal to anyone reading your code "hey, this is meant to be a partial update". If you use POST for updates what creates? Also POST? I'd use POST for creates, PUT for full updates and PATCH for partial updates. Of course, a quick Google search will reveal many different views on when you should use POST vs PUT vs PATCH so I guess go with what works for you and be 100% consistent in your app. – NoobsArePeople2 Feb 12 '16 at 0:37
6

For an update (POST) request, a field that is omitted should not be changed. To clear a field from it's value, it should be mentioned in the request with the value null or a normal value to change the value completely.
In your example, Classroom will keep the value 1A.

For a replace document (PUT) request, all the fields will be cleared and replaced with what is inside the request. So when a field is omitted, it will be cleared.
In you example, when you send a PUT request, Classroom will be null.

When using POST as a create request, the omitted fields will not be set, so Classroom stays null.

This is at least the way that is specified in the jsonapi.org specification (a specification for JSON responses on REST services):

If a request does not include all of the attributes for a resource, the server MUST interpret the missing attributes as if they were included with their current values. The server MUST NOT interpret missing attributes as null values.

Other specifications, like OData, describe the same behaviour. But as long as you document the implemented behaviour, it is your choice.

  • 1
    And it doesn't hurt to document what you are doing in the documentation of your API. – gnasher729 Feb 12 '16 at 8:27
  • 1
    Good documentation is the key here, but knowing what different standards say about it and what other people do or expect is useful when implementing your API. – David Perfors Feb 12 '16 at 9:06
  • David, thanks. That's very helpful and exactly the type of answer I'm looking for. I want my API to do the "expected" thing (as long as the expected thing is within the guidelines of http and REST). So if this is how jsonapi and odata are working, and it's kind of the de facto expected behavior, that's how I'll implement it. – richard Feb 13 '16 at 1:06
1

I think a good example is given by the OData standard, which calls these differential updates.

POST should be used for adding resources, and PUT to replace them (PUT is idempotent).

When PATCH was not a standard, OData actually introduced a MERGE method just to deal with the situation in your question. OData 3.0 in fact is declaring MERGE obsolete in favour of the official PATCH.

Anyway, POST should set missing properties to null, or delete them.

See also: Why isn't HTTP PUT allowed to do partial updates in a REST API?

  • Why? The client can easily delete missing properties by passing a null value. What you suggest forces the client to keep track of all properties, even those that the client isn't interested in at all, and to send them back to the server if all they want to do is change one single property. I would find that kind of API annoying to the extreme. – gnasher729 Feb 12 '16 at 8:28
  • @gnasher729 I have no idea of why I wrote that, sorry. It meant something, this morning... – bigstones Feb 12 '16 at 18:19
  • POST and PUT can both create, but in completely different ways. POST will create a resource, but the resultinig URI of the new resource is determined by the server. PUT creates a resource, but at a specified (by the client/request) location. – richard Feb 13 '16 at 1:07
  • @RichardDesLonde in general yes, but not in OData <= 3.0 (didn't check 4.0). – bigstones Feb 13 '16 at 16:37

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.