Как мне обращаться с иерархиями объектов в RESTful API?

В настоящее время я разрабатываю API для существующего PHP-приложения, и с этой целью я исследую REST как разумный архитектурный подход.

Я считаю, что у меня есть разумное понимание ключевых концепций, но я изо всех сил пытаюсь найти любого, кто занялся иерархиями объектов и REST.

Здесь проблема...

В иерархии бизнес-объектов [application] мы имеем:

Users 
 L which have one-to-many Channel objects
 L which have one-to-many Member objects

В самом приложении мы используем ленивый подход загрузки, чтобы заполнить объект User массивами этих объектов по мере необходимости. Я считаю, что в терминах OO это агрегирование объектов, но я видел различные несоответствия именования и не хочу начинать войну с точным соглашением об именах.

Теперь рассмотрим, что у меня есть некоторые слабо связанные объекты, которые я могу/не могу заполнить в зависимости от необходимости приложения.

С точки зрения REST, я пытаюсь выяснить, какой подход должен быть. Вот мое текущее мышление (учитывая GET только на данный момент):

Вариант 1 - полностью заполняет объекты:

GET api.example.com/user/{user_id}

Прочитайте объект User (ресурс) и верните объект User со всеми возможными предварительно загруженными и закодированными объектами Channel и Member (JSON или XML).

PROS: уменьшить количество объектов, не требуется обход иерархии объектов
CONS: объекты должны быть полностью заполнены (дорого)

Вариант 2 - заполнить основной объект и включить ссылки на другие ресурсы объекта:

GET api.example.com/user/{user_id}

Прочтите объект User (ресурс) и верните объект User User data и два списка.

Каждый список ссылается на соответствующий (дополнительный) ресурс i.e.

api.example.com/channel/{channel_id}
api.example.com/member/{member_id}

Я думаю, что это близко (или точно) к последствиям гипермедиа - клиент может получить другие ресурсы, если захочет (пока я помечаю их разумно).

PROS: клиент может выбрать загрузку подчиненных или иначе, лучшее разделение объектов как ресурсов REST
CONS: дополнительная поездка, необходимая для получения вторичных ресурсов

Вариант 3 - разрешить рекурсивные извлечения

GET api.example.com/user/{user_id}

Прочитайте объект User и включите ссылки на списки под-объектов i.e.

api.example.com/user/{user_id}/channels
api.example.com/user/{user_id}/members

вызов/channels вернет список ресурсов канала в форме (как указано выше):

api.example.com/channel/{channel_id}

PROS: первичные ресурсы раскрывают, куда идти, чтобы получить подпотоки, но не то, что они есть (больше RESTful?), не требуется, чтобы подчиненные были впереди, генераторы подчиненных списков (/channels и /members ) предоставляют интерфейсы (метод например), что делает ответ более полезным. CONS: теперь требуется три вызова для полного заполнения объекта

Вариант 4 - (пере) рассмотреть дизайн объекта для REST

Я повторно использую иерархию объектов [существующего] приложения и пытаюсь применить его к REST - или, возможно, более прямо, предоставить ему интерфейс API.

Возможно, иерархия объектов REST должна быть другой, или, возможно, новое мышление RESTful подвергает ограничения существующего дизайна объекта.

Любые мысли о вышеуказанном приветствовались.

Большое спасибо

Пол

Ответ 1

Нет причин не комбинировать их.

  • api.example.com/user/{user_id} - вернуть представление пользователя
  • api.example.com/channel/{channel_id} - вернуть представление канала
  • api.example.com/user/{user_id}/channels - возвращает список представлений каналов
  • api.example.com/user/{user_id}/channel_list - вернуть список идентификаторов каналов (или ссылки на их полные представления, используя приведенные выше ссылки).

Если вы сомневаетесь, подумайте о том, как вы будете отображать данные для пользователя без проблем API: пользователю нужны как индексные страницы ({user_id}/channel_list), так и полные виды ({user_id}/channels).

После этого просто поддерживайте JSON вместо (или в дополнение) HTML в качестве формата представления, и у вас есть REST.

Ответ 2

Лучшим советом, который я могу дать, является попытка избежать того, чтобы думать о вашем REST api как об экспорте ваших объектов. Ресурсы, которые вы создаете, должны поддерживать нужные вам случаи использования. При необходимости вы можете создать ресурсы для всех трех параметров:

api.example.com/completeuser/{id}
api.example.com/linkeduser/{id}
api.example.com/lightweightuser/{id}

Очевидно, мои имена немного тупые, но на самом деле неважно, как вы их называете. Идея заключается в том, что вы используете REST api для представления данных наиболее логичным образом для конкретного сценария использования. Если существует несколько сценариев, при необходимости создайте несколько ресурсов. Мне нравится думать, что мои ресурсы больше похожи на модели пользовательского интерфейса, а не на бизнес-объекты.

Ответ 3

Я бы порекомендовал Restful Obects, который является стандартом для демонстрации модели домена без проблем

Идея Restful Objects - предоставить стандартный универсальный интерфейс RESTful для моделей объектов домена, подвергая представлениям их структуры с помощью JSON и позволяя взаимодействовать с экземплярами объектов домена с помощью HTTP GET, POST, PUT и DELETE.

В соответствии со стандартом URI будут выглядеть следующим образом:

  • api.example.com/object/user/31
  • api.example.com/object/user/31/properties/username
  • api.example.com/object/user/31/collections/channels
  • api.example.com/object/user/31/collections/members
  • api.example.com/object/user/31/actions/someFunction
  • api.example.com/object/user/31/actions/someFunction/invoke

Существуют и другие ресурсы

  • api.example.com/services
  • api.example.com/domain-types

Спецификация определяет несколько первичных представлений:

  • объект (который представляет любой объект или услугу домена)
  • (ссылки на другие объекты)
  • свойство
  • коллекция
  • действие
  • результат действия (обычно содержащий либо объект, либо список, либо просто сообщения обратной связи)
  • а также небольшое количество вторичных представлений, таких как home и user

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

В качестве альтернативы представления могут быть использованы непосредственно при помощи приложения на заказ.

Ответ 4

Здесь мои выводы из многих часов поиска и ввода от респондентов здесь:

Если у меня есть объект, который эффективно является многокомпонентным объектом, мне нужно рассматривать его как единственный ресурс. Таким образом, если я получаю объект, все подчиненные должны присутствовать. Это необходимо для того, чтобы ресурс был кэшируемым. Если я частично загружаю объект (и предоставляю штамп ETag), тогда другие запрашивающие лица могут получить частичный объект, если они ожидали полного. Conclude - объекты должны быть полностью заполнены, если они становятся доступными в качестве ресурсов.

Связанные отношения объектов должны быть доступны как ссылки на другие (первичные) ресурсы. Таким образом, объекты можно обнаружить, пройдя API.

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

Надеюсь, что кто-то поможет