Ресурс REST со свойством List
Я хотел бы получить некоторые отзывы о моей нынешней архитектуре.
У меня есть ресурс "Person", доступный через запросы GET и PUT для: /users/people/{key}. Ресурс создает и принимает объекты "Персона" в формате JSON.
Это пример JSON, который GET /users/people/{key}
может вернуться:
{
"age":29,
"firstName":"Chiquita",
"phoneNumbers":[
{"key":"49fnfnsa0sas","number":"555-555-5555","deleted":false}
{"key":"838943bdfb-f","number":"777-777-7777","deleted":false}
]
}
Как видите, у "Person" есть несколько типичных полей, таких как "firstName" и "age", а также более сложное поле типа коллекции: "phoneNumbers".
Я пытаюсь спроектировать ресурсы так, чтобы при их обновлении клиенту нужно было только возвращать поля, которые нужно обновить. Например, чтобы обновить только имя человека:
PUT users/people/{key}
{
"firstName":"New first name",
}
Таким образом, намного меньше ненужной информации, передаваемой туда и обратно (степень меньше в зависимости от размера ресурса)
У меня вопрос, что мне делать со свойствами списка, такими как "phoneNumbers". Должен ли я написать более сложный код, который проверяет существующие ключи PhoneNumber в старом списке и не трогает их, если на них нет ссылок, обновляет их, если есть соответствующий ключ, и добавляет их, если существует PhoneNumber с новым ключом? Или я должен написать какой-то более простой код, который обрабатывает каждое свойство списка "phoneNumbers" как просто другое поле, которое полностью перезаписывается, если оно включено в тело запроса "PUT"? Существует ли общепринятый подход к этому, когда одна стратегия оказалась менее проблемной, чем другая? или я должен использовать свое усмотрение?
Спасибо!
3 ответа
Я думаю, что было бы разумнее просто сделать так, чтобы клиент загружал всю информацию для текущего человека каждый раз, когда что-то меняется. Однако этого может быть недостаточно, если:
- Много данных должно быть отправлено туда и обратно при изменении типичных сценариев.
- Несколько человек могут редактировать одного и того же человека одновременно.
Если ваши люди имеют большие объекты, вы можете рассмотреть возможность использования diff / patch. Перед отправкой новой версии сравните ее со старой версией. Если одноэлементное поле (например, firstName) изменилось, просто перечислите его в своем объекте JSON:
{
"firstName":"New first name"
}
Для набора телефонных номеров перечислите номера телефонов, которые нужно удалить, используя ключ, и укажите новые номера телефонов, которые нужно добавить, как обычно. Что-то вроде этого:
{
"+phoneNumbers":[
{"key":"123456789abc","number":"555-123-4567"}
],
"-phoneNumbers":[
"49fnfnsa0sas"
]
}
Вы также можете поискать в Google "json diff" и посмотреть, окажется ли какой-либо из найденных результатов полезным.
Как я уже говорил ранее, если у вас нет веских причин для перехода на эту глубину сложности, вероятно, лучше всего просто попросить клиента повторно загрузить весь объект person для его обновления.
Определение PUT заключается в том, что он должен иметь семантику замены. Глагол PATCH был введен для обеспечения возможности частичного обновления. Смотрите http://tools.ietf.org/html/rfc5789
Что касается того, как сделать формат diff, там действительно нет правильного или неправильного пути. Это действительно зависит от вашего контекста.
Как уже говорили другие, PUT требует замены всего ресурса. Тем не менее, как архитектор, вы разрабатываете ресурс. Возможно, запись Person содержит номера телефонов как часть этого. Или, может быть, это больше похоже на способ создания реляционной базы данных с номерами телефонов в отдельной таблице. В этом случае GET /users/people/{key} получит только имя и возраст, и вы определите параметры запроса, если вы хотите, чтобы номера телефонов вместе с именем. GET /users/userphone/{key} получит ресурс, содержащий телефонные номера человека, массив.
Возвращаясь к определению ресурса Person, содержащего номера телефонов внутри него, нет ничего плохого в использовании POST. Например, классическое использование POST - это опубликовать комментарий на веб-странице или удалить комментарий. Нет причины, по которой вы не можете определить операцию POST для добавления или удаления номера телефона. POST - это метод "что угодно", хороший или плохой.
(Я заметил, что на кнопке здесь написано "Опубликовать свой ответ", а не "Поставьте свой ответ", и по уважительной причине.)