Подтвердить что ты не робот

Должны ли вложенные отношения отображаться в URL-адресах для JSON API?

Я пытаюсь следовать JSON API. Мне нужно открыть доступ CRUD к вложенным ресурсам: обзоры продуктов.

До использования JSON API я ожидал бы интерфейс REST:

GET    /products/:product_id/reviews     - list reviews for a product
POST   /products/:product_id/reviews     - add a review for a product
PATCH  /products/:product_id/reviews/:id - update a review for a product
DELETE /products/:product_id/reviews/:id - delete a review for a product

Я вижу некоторое упоминание о вложенной структуре, подобной этой в спецификации:

Например, URL для комментариев фотографий будет выглядеть следующим образом:

/photos/1/comments

Но я не уверен, предназначена ли эта структура для всех действий.

С одной стороны, POST /products/:product_id/reviews для создания кажется излишним, если я собираюсь указать продукт в теле POST под данными обзора relationships.

С другой стороны, если полезно удалить идентификатор продукта при удалении отзыва (возможно, это не так), DELETE /products/:product_id/reviews/:id кажется единственным разумным способом сделать это; люди спорят о том, разрешено ли тело запроса для запросов DELETE.

Я мог бы вложить несколько запросов, а не другие:

GET    /products/:product_id/reviews  - list reviews for a product
POST   /products/:product_id/reviews  - add a review for a product
PATCH  /reviews/:id                   - update a review
DELETE /reviews/:id                   - delete a review

Но это кажется странно непоследовательным.

Я никогда не мог бы гнездиться:

GET    /reviews     - list reviews for the product specified in params
POST   /reviews     - add a review for the product specified in params
PATCH  /reviews/:id - update a review
DELETE /reviews/:id - delete a review

Но это кажется неудобным и, похоже, не соответствует первой цитате, которую я сделал из документов.

Должны ли вложенные отношения ресурсов отображаться в URL-адресе при использовании JSON API?

4b9b3361

Ответ 1

Мне очень нравится ваш вопрос, так как у меня такие же мысли. Я озадачен тем, что никто не оставил ответа.

Я использую JSON API чуть больше года на производственной системе, и я бы хотел дать два цента.

Сначала, когда я начал проект, который собирался использовать JSON API, я сомневался в вложенных и не вложенных ресурсах. Затем я столкнулся с проблемами с вложенными ресурсами, которых можно было бы избежать с помощью не вложенных ресурсов.

Чтобы использовать те же пути, что и в вашем примере, рассмотрите конечную точку GET /products/:product_id/reviews. Когда это сделано, очень важно развернуть обзор под продуктом, потому что мы изначально показываем отзывы в контексте продукта. Все хорошо.

Затем мы захотим создать страницу в интерфейсе, в которой будет показан пользователь и все отзывы, которые пользователь создал. Хотя у нас уже есть конечная точка для получения отзывов, нам нужно будет создать новую, например. GET /users/:id/reviews.

Если бы мы только что положили первую конечную точку на GET /reviews с фильтром ?filter[product_id]=:id, мы могли бы просто добавить новый фильтр к этой конечной точке, что имеет смысл ИМО.

Я использую вложенные ресурсы, но только для ресурсов singleton, таких как GET /users/:id/email_settings и нескольких других особых случаев, когда это имеет смысл.

По моему опыту, это облегчает в будущем, если каждый ресурс считается независимым от других ресурсов. Существуют ресурсы и отношения между ресурсами. Ни один ресурс "не владеет" другим ресурсом в контексте API (в контексте бизнес-логики это другая история).

Я работал с этой стратегией, и это все еще удивляет меня, насколько хорошо он работает при добавлении новых функций к существующим конечным точкам и при добавлении новых конечных точек.

Ответ 2

Если вы приехали из лагеря CQRS, вы поймете, почему дизайн Restful API иногда неудобен. Это неудобно, потому что, естественно, действия Query (GET) и Mutation (POST, PATCH, DELETE) должны разговаривать на двух разных языках. Действия запроса, естественно ориентированные на отношения и богатые данными; в то время как мутационные действия нет. Таким образом, легко использовать вложенный URL-адрес для обхода между объектами отношений. Но Mutation вы должны предоставить достаточно информации для задач. Иногда это избыточно, как ваш пример Post. Иногда отсутствует, например, ваш пример DELETE. Иногда у вас есть задача привлечь много ресурсов; вы не знаете, куда положить.

Вы должны проверить API-интерфейс Facebook Graph или API-интерфейс Azure Graph, они столкнулись с теми же проблемами и имеют несколько хороших решений. Важно, чтобы вы следовали последовательному дизайну. Некоторые правила:

  • DELETE, UPDATE всегда направлять ресурсы.
  • Использование POST с вложенным ресурсом, если вы хотите создать как объект, так и основные отношения. Вторичные отношения должны быть установлены в BODY. Если у вас есть два равных отношения, рассмотрите оба вложенных API.
  • Использовать POST против поддельного ресурса, чтобы задачи включали в себя множество ресурсов.

    POST/transferfund

  • Использование POST против фальшивых отношений для задач не может соответствовать любым HTTP-глаголам. Например, вы хотите иметь тело для действия удаления, использовать

    POST/ресурс/id/deleteItForMe {reason: "Ненавижу" }