REST API - включает связанные детали объекта или только идентификаторы

Какая лучшая дизайнерская практика?

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

Должен ли я по запросу api.example.org/cars/1 отвечать только с идентификатором на эти ресурсы (так что, если кому-то нужна информация о них, требуется другой вызов API в api.example.org/type/1)

{
    "id": 1,
    "name": "Some Car",
    "types": [
        1,
        2
    ]
}

или предоставить сведения об этих ресурсах, а также

{
    "id": 1,
    "name": "Some Car",
    "types": [
        {
            "id": 1,
            "name": "Some Type",
            "something": "Blah"
        },
        {
            "id": 2,
            "name": "Some Type",
            "something": "Blah"
        }
    ]
}

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

Ответ 1

Это касается одного из основных принципов REST, называемого HATEOAS (Hypermedia как механизм состояния приложения).

Идентификаторы объектов бесполезны и бессмысленны для клиентов. Что вы с ними делаете? Подключите их к функции поиска? Построить новый URI с ними, добавленным к концу? Позвоните по номеру 1-800 и спросите, что с ними делать? Распечатайте их на бумаге и отправьте их в правительственное агентство, которое помогает клиентам API найти следующие шаги?

Просто верните полный URI, все время. Идентификатор, предоставленный клиенту, всегда должен быть URI - это то, что однозначно идентифицирует данный ресурс и может использоваться для извлечения, обновления или удаления.

Ответ 2

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

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

{
    "id": 1,
    "name": "Some Car",
    "types": [
        {
            "location": "api.example.org/type/1"
        },
        {
            "location": "api.example.org/type/2"
        }
    ]
}