首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >来自RESTful应用编程接口的分页响应有效负载

来自RESTful应用编程接口的分页响应有效负载
EN

Stack Overflow用户
提问于 2012-08-29 06:47:57
回答 5查看 126.2K关注 0票数 92

我想在我的RESTful应用程序接口中支持分页。

我的API方法应该通过/products/index返回产品的JSON列表。然而,可能有数千种产品,我想浏览一下它们,所以我的请求应该类似于:

代码语言:javascript
运行
复制
/products/index?page_number=5&page_size=20

但是我的JSON响应应该是什么样子呢?API使用者通常会期望响应中包含分页元数据吗?或者只需要一系列产品?为什么?

看起来Twitter的API包含了元数据:https://dev.twitter.com/docs/api/1/get/lists/members (参见示例请求)。

对于元数据:

代码语言:javascript
运行
复制
{
  "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"
    }
  ]
}

只有一组产品(没有元数据):

代码语言:javascript
运行
复制
[
  {
    "id": 1,
    "name": "Widget #1"
  },
  {
    "id": 2,
    "name": "Widget #2"
  },
  {
    "id": 3,
    "name": "Widget #3"
  }
]
EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2012-08-29 13:01:47

ReSTful API主要由其他系统使用,这就是我将分页数据放在响应头中的原因。但是,一些API使用者可能无法直接访问响应头,或者可能在您的API上构建UX,因此提供一种在JSON响应中检索(按需)元数据的方法是有好处的。

我认为您的实现应该默认包含机器可读的元数据,并在请求时包含人类可读的元数据。如果您愿意,人类可读的元数据可以随每个请求一起返回,或者最好是通过查询参数(例如include=metadatainclude_metadata=true )按需返回。

在您的特定场景中,我将在记录中包含每个产品的URI。这使得API使用者可以很容易地创建指向各个产品的链接。我也会根据我的寻呼请求的限制设置一些合理的期望。实现和记录页面大小的默认设置是一种可接受的做法。例如,GitHub's API将默认页面大小设置为30条记录,最大为100条,另外还设置了查询次数的速率限制。如果您的API有默认的页面大小,那么查询字符串可以只指定页面索引。

在人类可读的场景中,当导航到/products?page=5&per_page=20&include=metadata时,响应可能是:

代码语言:javascript
运行
复制
{
  "_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 headers

代码语言:javascript
运行
复制
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)

...and可能是自定义的total-count响应头,如果您这样选择的话:

代码语言:javascript
运行
复制
total-count: 521

以人为中心的元数据中显示的其他分页数据对于以机器为中心的元数据可能是多余的,因为链接标头让我知道我在哪个页面上以及每页的数量,并且我可以快速检索数组中的记录数量。因此,我可能只会为总计数创建一个标题。您可以随时改变主意,并添加更多元数据。

顺便说一句,您可能注意到我从您的URI中删除了/index。一个普遍接受的约定是让您的ReST端点公开集合。将/index放在末尾会使这一点变得有点混乱。

这些只是我在使用/创建API时想要的几件事。希望这能有所帮助!

票数 122
EN

Stack Overflow用户

发布于 2012-08-29 08:13:40

作为编写了几个使用REST服务的库的人,让我从客户的角度来解释为什么我认为将结果包装在元数据中是可行的:

  • 没有总计数,客户端如何知道它还没有收到所有的结果集并且应该继续对结果集进行分页?在没有执行向前看下一页的UI中,在最坏的情况下,这可能表示为一个Next/More链接,该链接实际上没有在响应中获取更多的data.
  • Including元数据,从而允许客户端跟踪更少的状态。现在,我不必将REST请求与响应相匹配,因为响应包含重新构造请求状态所需的元数据(在本例中,游标指向数据集)。
  • 如果状态是响应的一部分,则可以同时对同一数据集执行多个请求,并且可以按请求到达的任何顺序处理请求,而不一定是我发出请求的顺序。

还有一个建议:和Twitter API一样,应该用直接的索引/游标替换page_number。原因是,API允许客户端设置每个请求的页面大小。返回的page_number是客户端到目前为止请求的页面数量,还是给定上次使用的page_size的页面数量(几乎可以肯定是后者,但为什么不完全避免这种多义性呢)?

票数 30
EN

Stack Overflow用户

发布于 2016-08-02 21:41:20

我建议添加相同的头文件。将元数据移动到头部有助于摆脱resultdatarecords等信封,而响应正文只包含我们需要的数据。如果您也生成分页链接,则可以使用Link header。

代码语言:javascript
运行
复制
    HTTP/1.1 200
    Pagination-Count: 100
    Pagination-Page: 5
    Pagination-Limit: 20
    Content-Type: application/json

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

有关详细信息,请参阅:

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

对于swagger文件:

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

票数 25
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/12168624

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档