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

时间:2018-08-30 00:22:28

标签: json bash api 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的原因是它是我所知道的唯一编程。

尝试

(基于this question and answer

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

结果

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

  • 第一个startIndex应该是0,但是代码使startIndex 100成为可能。我用i尝试了多种变体,但仍然失败。
  • [edit:解决了,谢谢@weirdan] list":nullnext":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" : [ {
...

中间页

{
  "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" : [ {
...

最终页面

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

空页

{
  "itemsPerPage" : 100,
  "list" : [ ],
  "startIndex" : 500
}

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

1 个答案:

答案 0 :(得分:1)

假设我关于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