superwelling
superwelling

Reputation: 109

Updating a resource through REST (PUT/POST)

When updating a resource via REST, should one include in the body just the values to update, or the whole object (current values and values to update)?

If a User object looks like this

User (id, name, age, sex)  

and I want to update only his name and age, should my request look like this:

PUT /users/1

{"name":"john","age":18}

or like this:

PUT /users/1

{"name":"john","age":18, "sex":"m"}

And what should that look like on the server side?

@RequestMapping(value = "/{userId}", method = PUT, consumes = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<String> updateUser(@PathVariable final int userId, @RequestBody User u){
    //fetch user by ID 
    user.setName(u.getName())
    user.setAge(u.getAge())
    user.setSex(u.getSex()) //this will be empty?

    return new ResponseEntity<String>(gson.toJson(user), HttpStatus.OK);
}

Or alternatively I could find out which variables were not included in the request body and do something like this

if(u.getName()!=null){
     user.setName(u.getName())
}
if(u.getAge()!=null){
     user.setAge(u.getAge())
}
if(u.getSex()!=null){
     user.setSex(u.getSex())
}

Is there a right/wrong way to achieve this, or is it a case of just doing what's easiest?

Upvotes: 1

Views: 3143

Answers (1)

jwdev
jwdev

Reputation: 61

PUT requests must be idempotent and should provide as its payload a complete representation of the entity it is replacing. (https://www.rfc-editor.org/rfc/rfc7231#section-4.3.4)

The PUT method requests that the state of the target resource be created or replaced with the state defined by the representation enclosed in the request message payload.

A partial JSON object PUT request would be a PATCH with Content-Type: application/merge-patch+json (https://www.rfc-editor.org/rfc/rfc7396)

Things to think about. You might have multiple clients updating an entity at the same time, using a PUT could end up overwriting changes other clients have made.

In that case you might want to set a pre-condition to check if the object was updated between the time that the requesting client fetched the entity, made changes and submitted the PUT/PATCH request. For example the pre-condition could be a last updated timestamp, hash (Etag) or a version number; Or you could use a "last write wins" approach which is common in eventually consistent systems. It all depends on your system and the situation.

On the server side, if you support partial updates then as you have provided in your example, you would identify the set of properties included in the request and only set the specific ones that were provided.

Upvotes: 5

Related Questions