当前位置: 首页 > 知识库问答 >
问题:

来自RESTful API的分页响应有效负载

燕宜修
2023-03-14

我想在RESTful API中支持分页。

我的API方法应该通过/Products/index返回产品的JSON列表。但是,可能有成千上万的产品,我想浏览它们,所以我的请求应该如下所示:

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

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

看起来Twitter的API包含元数据: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个答案

龙景澄
2023-03-14

作为一个为使用REST服务编写了多个库的人,让我从客户机的角度介绍一下为什么我认为将结果包装成元数据是一种可行的方法:

  • 如果没有总数,客户机怎么知道它还没有收到所有的数据,应该继续在结果集中分页?在没有执行前瞻下一页的UI中,在最坏的情况下,这可能表示为下一个/多个链接,实际上没有获取更多数据

还有一个建议:像推特API一样,应该用直接的索引/光标替换page\u编号。原因是,API允许客户端设置每个请求的页面大小。返回的page\u number是客户端迄今为止请求的页数,还是给定上次使用的page\u大小的页数(几乎可以肯定是后者,但为什么不完全避免这种歧义)?

汪建德
2023-03-14

我建议添加相同的标头。将元数据移动到标头有助于摆脱信封,如结果数据记录和响应正文仅包含我们需要的数据。如果您也生成分页链接,则可以使用链接标头。

    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

姚智
2023-03-14

ReSTful API主要被其他系统使用,这就是为什么我将分页数据放在响应标头中。但是,一些API使用者可能无法直接访问响应标头,或者可能正在通过您的API构建用户体验,因此提供一种在JSON响应中检索(按需)元数据的方法是一个优势。

我相信您的实现应该默认包含机器可读元数据,并在请求时包含人类可读元数据。如果您愿意,可以在每次请求中返回人类可读元数据,或者最好通过查询参数按需返回,例如include=元数据include_metadata=true

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

在人类可读的场景中,当导航到产品时?页码=5

{
  "_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

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

另外,您可能会注意到我从您的URI中删除了索引。普遍接受的约定是让ReSTendpoint公开集合。在末端有索引,使其略微变脏。

这些只是我在使用/创建API时喜欢的一些东西。希望有帮助!

 类似资料:
  • 问题内容: 以下代码调用错误。我在参考资料中找不到关于此的任何信息。’=’运算符右侧缺少空格是一个错误。 可以编译此语法的任何其他组合。根据我们对Swift的了解,有人知道这是否真的是无效的语法吗? 编辑:错误响应是: 答案:这段摘录似乎回答了我的问题。我只是找不到最长的时间: 运算符周围的空白用于确定将运算符用作前缀运算符,后缀运算符还是二进制运算符。以下规则总结了此行为: 如果运算符的两边或两

  • 对于反应式编程和SpringWebClient来说,这是一个相当新的概念,所以我正在尝试了解它,本质上,我有一个分页的结果列表,可以从一个REST服务中使用,该服务使用一个链接响应头进行响应,该响应头带有一个与下一页结果(如果存在)相关的URI。我想把所有的页面都收集到一个通量中。默认情况下,生成的ApicClient具有如下内容 那么,我是否需要对结果的每一页进行某种递归调用,将每一页合并成一个

  • --我只是试图从html中检索数据,这样我就可以从应用程序的url中显示更新的数据,是Volly的方式还是我应该使用更简单的方法? 下面是我的volley StringRequest和RequestQueue:

  • 我的应用程序中使用了Google的oauth2,其中id_token是由句点分隔的字符串。我在这里读到,id_token被划分为三部分,第二部分包含实际有效负载。如果我将字符串拆分并解码第二个值,我将使用我的帐户得到我期望的结果。但我不明白的是,当我尝试使用我妻子的帐户时,如果我将第二部分解析为json,就会出现“意外字符”错误。 我尝试过从控制台获取字符串并通过在线Base64解码器运行它,但确

  • 您好,我在Django中有一个项目,它对不同的数据库执行多个查询,并在多个endpoint中返回它们,为此我使用Pandas和DRF(APIViews)。 当响应很长,逻辑上服务器运行内存溢出时,问题就出现了,我知道我需要分页结果,但我没有找到方法,因为我不使用模型或序列化器,我用熊猫做原始查询进行查询。 有没有办法像我这样分页结果? 我留下了一些代码片段。

  • 我在验证从ADFS服务器获得的SAML响应时遇到了问题。我以url的形式获得响应,例如,而是http://www.w3.org/2001/04/xmldsig-more#rsa-sha256。我设法解码了响应,但无法找到使用给定签名验证响应的方法。 我的主要问题是签名有一个非常意外的格式。由于给定的签名算法,我希望签名的长度为32字节,但是当我base64-decode签名时,我得到的是长度为25