Разбиение на страницы полезная нагрузка ответ от API с поддержкой REST


Я хочу поддерживать разбиение на страницы в моем RESTful API.

мой метод API должен возвращать список JSON продукта через /products/index. Тем не менее, есть потенциально тысячи продуктов, и я хочу пролистать их, поэтому мой запрос должен выглядеть примерно так:

/products/index?page_number=5&page_size=20

но как должен выглядеть мой ответ JSON? Будут ли потребители API обычно ожидать метаданных разбиения на страницы в ответе? Или только массив продуктов необходим? Зачем?

это похоже, что API Twitter включает в себя метаданные:https://dev.twitter.com/docs/api/1/get/lists/members (см. пример запроса).

с метаданными:

{
  "page_number": 5,
  "page_size": 20,
  "total_record_count": 521,
  "records": [
    {
      "id": 1,
      "name": "Widget #1"
    },
    {
      "id": 2,
      "name": "Widget #2"
    },
    {
      "id": 3,
      "name": "Widget #3"
    }
  ]
}

просто массив продуктов (без метаданных):

[
  {
    "id": 1,
    "name": "Widget #1"
  },
  {
    "id": 2,
    "name": "Widget #2"
  },
  {
    "id": 3,
    "name": "Widget #3"
  }
]
3 60

3 ответа:

RESTful API используются в основном другими системами, поэтому я помещаю данные подкачки в заголовки ответов. Однако некоторые потребители API могут не иметь прямого доступа к заголовкам ответов или могут создавать UX над вашим API, поэтому предоставление способа получения (по требованию) метаданных в ответе JSON является плюсом.

Я считаю, что ваша реализация должна включать машиночитаемые метаданные по умолчанию и читаемые человеком метаданные при запросе. Человек-читаемый метаданные могут быть возвращены с каждым запросом, если вы хотите или, предпочтительно, по требованию с помощью параметра запроса, такого как include=metadata или include_metadata=true.

в вашем конкретном случае, я бы включил URI для каждого продукта с записью. Это упрощает для потребителя API создание ссылок на отдельные продукты. Я бы также установил некоторые разумные ожидания в соответствии с пределами моих запросов на пейджинг. Реализация и документирование параметров по умолчанию для размера страницы является приемлемым практиковать. Например, API GitHub устанавливает размер страницы по умолчанию в 30 записей с максимумом 100, а также устанавливает ограничение скорости на количество раз, когда вы можете запросить API. Если ваш API имеет размер страницы по умолчанию, то строка запроса может просто указать индекс страницы.

в удобочитаемом сценарии при переходе к /products?page=5&per_page=20&include=metadata, ответ может быть:

{
  "_metadata": 
  {
      "page": 5,
      "per_page": 20,
      "page_count": 20,
      "total_count": 521,
      "Links": [
        {"self": "/products?page=5&per_page=20"},
        {"first": "/products?page=0&per_page=20"},
        {"previous": "/products?page=4&per_page=20"},
        {"next": "/products?page=6&per_page=20"},
        {"last": "/products?page=26&per_page=20"},
      ]
  },
  "records": [
    {
      "id": 1,
      "name": "Widget #1",
      "uri": "/products/1"
    },
    {
      "id": 2,
      "name": "Widget #2",
      "uri": "/products/2"
    },
    {
      "id": 3,
      "name": "Widget #3",
      "uri": "/products/3"
    }
  ]
}

для машиночитаемых метаданных я бы добавил заголовки ссылке к ответ:

Link: </products?page=5&perPage=20>;rel=self,</products?page=0&perPage=20>;rel=first,</products?page=4&perPage=20>;rel=previous,</products?page=6&perPage=20>;rel=next,</products?page=26&perPage=20>;rel=last

(значение заголовка ссылки должно быть urlencoded)

...и, возможно, обычай total-count заголовок ответа, если вы так выбираете:

total-count: 521

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

в сторону, вы можете заметить, что я удалил /index из вашего URI. Общепринятое соглашение заключается в том, чтобы ваша конечная точка ReST предоставляла коллекции. Имея /index в конце мутит, что слегка.

это всего лишь несколько вещей, которые я хотел бы иметь при потреблении / создании API. Надеюсь, это поможет!

Как кто-то, кто написал несколько библиотек для использования служб REST, позвольте мне дать вам точку зрения клиента на то, почему я думаю, что обертывание результата в метаданные-это путь:

  • без общего количества, как клиент может знать, что он еще не получил все, что есть, и должен продолжать листать через результирующий набор? В пользовательский интерфейс, который не смотрит вперед на следующую страницу, в худшем случае это может быть представлено следующим более/ссылка, которая не на самом деле получить больше данных.
  • включение метаданных в ответ позволяет клиенту отслеживать меньше состояния. Теперь мне не нужно сопоставлять мой запрос REST с ответом, поскольку ответ содержит метаданные, необходимые для восстановления состояния запроса (в этом случае курсор в набор данных).
  • Если состояние является частью ответа, я могу одновременно выполнять несколько запросов в один и тот же набор данных, и я могу обрабатывать запросы в любом порядке, в котором они поступают в котором не обязательно порядок, в котором я сделал запросы.

и предложение: как Twitter API, вы должны заменить page_number прямым индексом / курсором. Причина в том, что API позволяет клиенту установить размер страницы для каждого запроса. Является ли возвращаемый page_number количеством страниц, которые клиент запросил до сих пор, или номером страницы, заданным последним используемым page_size (почти наверняка более поздним, но почему бы не избежать такой двусмысленности вообще)?

Я бы рекомендовал добавить заголовки для того же. Перемещение метаданных в заголовки помогает избавиться от оболочек, таких как result,data или records и тело ответа содержит только необходимые нам данные. Вы можете использовать ссылке заголовок, если вы создаете ссылки на страницы тоже.

    HTTP/1.1 200
    Pagination-Count: 100
    Pagination-Page: 5
    Pagination-Limit: 20
    Content-Type: application/json

    [
      {
        "id": 10,
        "name": "shirt",
        "color": "red",
        "price": ""
      },
      {
        "id": 11,
        "name": "shirt",
        "color": "blue",
        "price": ""
      }
    ]

Подробнее см.:

https://github.com/adnan-kamili/rest-api-response-format

для чванства файл:

https://github.com/adnan-kamili/swagger-response-template