在 Bash 循环中检测分页 cURL 响应的最后一页

hcd*_*ocs 4 api bash json curl jq

目标

使用 cURL 和 Bash 将分页 REST API 调用中的所有对象包含在单个 JSON 文件中。此组合列表将输入到 Power BI 报告中。

细节

一个请求最多返回 100 个对象。总共有 400 多个对象。总量随着时间的推移而增长。我不想维护包含类似内容的脚本,for set in 0 100 200 300 400 ; do因为它需要我手动将集合与当前的对象数量匹配。为了节省人力,我想要一个脚本来自动检测最终页面何时被处理然后中断。

为了实现我的目标,到目前为止我提出的计划是将每个 100 个项目的增量集提取到自己的 JSON 文件中,然后cat使用 JQ 将它们组合起来并提取相关的 JSON 键/值。使用 Bash 的原因是它是我所知道的唯一编程。

试图

(基于此问答

for ((i=0; ; i+=100)); do
    contents=$(curl -u "username:password" -H "Content-Type: application/json" "https://<url>/api/core/v3/places?count=100&startIndex=$i")
    echo "$contents" > $i.json
    if [[ $contents =~ 'list" : [ ]' ]]
    then break
    fi
done
Run Code Online (Sandbox Code Playgroud)

结果

除第一页和最后一页外,所有页面均按预期导出:

  • 第一个startIndex应该是0但代码使startIndex 100. 我尝试了许多变体,i但仍然失败。
  • [编辑:已解决,谢谢@weirdan] 既不循环list":null也不next":null结束循环。该脚本无限期地导出递增的 JSON 文件。~

参考

返回的分页 JSON 的第一页

{
  "itemsPerPage" : 100,
  "links" : {
    "next" : "https://<url>/api/core/v3/places?sort=titleAsc&count=100&startIndex=0" <--- with my script, startIndex is erroneously 100
  },
  "list" : [ {
...
Run Code Online (Sandbox Code Playgroud)

中间页

{
  "itemsPerPage" : 100,
  "links" : {
    "previous" : "https://<url>/api/core/v3/places?sort=titleAsc&count=100",
    "next" : "https://<url>/api/core/v3/places?sort=titleAsc&count=100&startIndex=200"
  },
  "list" : [ {
...
Run Code Online (Sandbox Code Playgroud)

最后一页

{
  "itemsPerPage" : 100,
  "links" : {
    "previous" : "https://<url>/api/core/v3/places?sort=titleAsc&count=100&startIndex=400"
  },
  "list" : [ {
...
Run Code Online (Sandbox Code Playgroud)

空页

{
  "itemsPerPage" : 100,
  "list" : [ ],
  "startIndex" : 500
}
Run Code Online (Sandbox Code Playgroud)

感谢您的任何建议或想法。

wei*_*dan 6

假设我的理论startIndex成立并实施@CharlesDuffy 的关于 的建议jq,这就变成了

for ((i=0; ; i+=100)); do
    contents=$(curl -u "username:password" -H "Content-Type: application/json" "https://<url>/api/core/v3/places?count=100&startIndex=$i")
    echo "$contents" > $i.json
    if jq -e '.list | length == 0' >/dev/null; then 
       break
    fi <<< "$contents"
done
Run Code Online (Sandbox Code Playgroud)