По моим сведениям:
-
PUT
- обновить объект со всем его представлением (заменить) -
PATCH
- обновлять объект только с заданными полями (обновление)
Я использую Spring для реализации довольно простого HTTP-сервера. Когда пользователь хочет обновить свои данные, ему нужно сделать HTTP PATCH
до некоторой конечной точки (пусть говорят: api/user
). Его тело запроса сопоставляется с DTO через @RequestBody
, который выглядит следующим образом:
class PatchUserRequest {
@Email
@Length(min = 5, max = 50)
var email: String? = null
@Length(max = 100)
var name: String? = null
...
}
Затем я использую объект этого класса для обновления (исправления) объекта пользователя:
fun patchWithRequest(userRequest: PatchUserRequest) {
if (!userRequest.email.isNullOrEmpty()) {
email = userRequest.email!!
}
if (!userRequest.name.isNullOrEmpty()) {
name = userRequest.name
}
...
}
Я сомневаюсь, что если клиент (например, веб-приложение) хотел бы очистить свойство? Я бы проигнорировал такое изменение.
Как я могу узнать, хочет ли пользователь очистить свойство (он отправил меня пустым намеренно) или он просто не хочет его менять? В обоих случаях он будет null в моем объекте.
Здесь я вижу два варианта:
- Согласитесь с клиентом, что если он хочет удалить свойство, он должен отправить мне пустую строку (но как насчет дат и других нестроковых типов?)
- Остановить использование сопоставления DTO и использовать простую карту, которая позволит мне проверить, было ли поле пустым или вообще не указано. Как насчет проверки тела запроса? Я использую
@Valid
прямо сейчас.
Как следует надлежащим образом обрабатывать такие случаи в соответствии с REST и всеми хорошими практиками?
EDIT:
Можно сказать, что PATCH
не следует использовать в таком примере, и я должен использовать PUT
для обновления моего пользователя. Но тогда, что о обновлениях API (например, добавление нового свойства)? Я должен был бы изменить свой API (или конечную точку пользователя версии самостоятельно); после каждого изменения пользователя api/v1/user
, который принимает PUT
со старым телом запроса, api/v2/user
, который принимает PUT
с новым телом запроса и т.д. Я думаю, что это не решение и PATCH
существует по причине.