According to my knowledge:
PUT
- update object with its whole representation (replace)PATCH
- update object with given fields only (update)
I'm using Spring to implement a pretty simple HTTP server. When a user wants to update his data he needs to make a HTTP PATCH
to some endpoint (let's say: api/user
). His request body is mapped to a DTO via @RequestBody
, which looks like this:
class PatchUserRequest {
@Email
@Length(min = 5, max = 50)
var email: String? = null
@Length(max = 100)
var name: String? = null
...
}
Then I use an object of this class to update (patch) the user object:
fun patchWithRequest(userRequest: PatchUserRequest) {
if (!userRequest.email.isNullOrEmpty()) {
email = userRequest.email!!
}
if (!userRequest.name.isNullOrEmpty()) {
name = userRequest.name
}
...
}
My doubt is: what if a client (web app for example) would like to clear a property? I would ignore such a change.
How can I know, if a user wanted to clear a property (he sent me null intentionally) or he just doesn't want to change it? It will be null in my object in both cases.
I can see two options here:
- Agree with the client that if he wants to remove a property he should send me an empty string (but what about dates and other non-string types?)
- Stop using DTO mapping and use a simple map, which will let me check if a field was given empty or not given at all. What about request body validation then? I use
@Valid
right now.
How should such cases should be properly handled, in harmony with REST and all good practices?
EDIT:
One could say that PATCH
shouldn't be used in such an example, and I should use PUT
to update my User. But what about model changes (e.g. adding a new property)? I would have to version my API (or the user endpoint alone) after every User change. E.g. I would have api/v1/user
endpoint which accepts PUT
with an old request body, and api/v2/user
endpoint which accepts PUT
with a new request body. I guess it's not the solution and PATCH
exists for a reason.