尝试在对API端点的Bash / Shell POST请求的JSON数据中包含动态变量

eivnm1vs  于 2023-02-20  发布在  Shell
关注(0)|答案(4)|浏览(147)

我正在尝试使用Bash提交POST请求,该请求包含JSON数据,其变量等于随机字符串的变量。我通过解析一个文件动态获取字符串,该文件的内容可能不同...并且可能包含正则表达式字符和新行。
我将在这里提供一个示例字符串,其中包含一个curl请求,该请求可以成功地与我将此请求发送到的API配合使用。我只能通过将字符串硬编码到JSON数据中来完成请求,而不能在为字符串分配变量(例如**stringVar**)并在JSON数据中使用该变量时完成请求。如果我将此操作搞砸了,我肯定会需要一些帮助
我的工作shell脚本如下所示

#!/bin/bash

curl -i -H "Authorization: Bearer <MY_API_TOKEN>" -H "Content-Type: application/json" -H "Accept: application/json" -X POST 'https://api.example.com/v1/endpoint' -d '{
    "name": "my-project",
    "files": [
        {
            "data": "helloWorldFunction() {\n echo \"hello world\" \n}"
        },
    ],
}'

这是可行的,但是我需要将数据的值从字符串**helloWorldFunction(){\n echo“hello world”\n}**更改为变量
我已经尝试过在JSON内容中以不同的方式设置变量,例如,我尝试过将shell脚本更改为

#!/bin/bash

stringVar="helloWorldFunction() {\n echo \"hello world\" \n}"

curl -i -H "Authorization: Bearer <MY_API_TOKEN>" -H "Content-Type: application/json" -H "Accept: application/json" -X POST 'https://api.example.com/v1/endpoint' -d '{
    "name": "my-project",
    "files": [
        {
            "data": "${stringVar}"
        },
    ],
}'

我试过像这样设置变量
“${字符串变量}”|变为${stringVar}
“$字符串变量”|变成了“$stringVar”
以及
“${字符串变量}”
“”$字符串变量“”
两者似乎都返回此错误{"error":{"code":"bad_request","message":"Invalid JSON"}}curl: (3) unmatched brace in URL position 1: {\n
以及
字符串变量
stringVar
$字符串变量
“$字符串变量”
“"$字符串变量””
${字符串变量}
似乎都返回此错误{"error":{"code":"bad_request","message":"Invalid JSON"}}
啊,任何关于我做错了什么的帮助都是很好的。提前感谢你们

c90pui9n

c90pui9n1#

为了插入变量的值,需要用双引号将字符串括起来("),但JSON也需要文字双引号。
最简单的解决方案可能是使用here-document将数据输入到curl的标准输入中,如@Gilles Quénot的答案所示,但您仍然可以通过命令行传递它;你只需要小心引用。
这是一种方法:

curl ... -d '{
  "name": "my-project",
  "files": [
    {
        "data": "'"$stringVar"'"
    }
  ]
}'

这里的JSON大部分包含在单引号中('... ')。但是,在打开将包含data的值的文字对" s之后,我们立即关闭单引号并将shell引用模式切换为双引号,以便包含$stringVar的值。对于JSON的其余部分,我们回到单引号中,从data值前后的文字双引号开始。
在使用+进行字符串连接的语言中,它看起来像'... "data": "' + "$stringVar" + '"... ',但在shell中,您只是将字符串放在彼此旁边,而没有操作符来连接它们。
作为一种替代方法,您可以将整个内容放在双引号中,但需要使用反斜杠来包含JSON中的文字双引号:

curl ... -d "{
  \"name\": \"my-project\",
  \"files\": [
    {
      \"data\": \"$stringVar\"
    }
  ]
}"

因此,如果您从普通JSON开始,则需要进行更多的更改;它看起来也更乱,海事组织。
您还可以使用一个知道如何构建JSON的工具,让它担心引用等问题。下面是使用jq构建JSON的一种方法:

jq -n --arg data "$stringVar" '{ 
  "name": "my-project", 
  "files": [ 
    { 
      "data": $data 
    } 
  ] 
}'

使用--argjq中创建一个变量-我将其命名为data-然后可以将其包含在语法为$varname的表达式中(在本例中为$data)。我们将文本$data传递给jq,而jq本身会将其替换为变量的值(作为第二个参数传递给--arg)。
还有一个叫做jo的工具,它并不操作JSON,而是从更容易在shell中生成的输入生成JSON。下面是用它构造所需对象的一种方法:

jo name=my-project files="$(jo -a "$(jo data="$stringVar")")"

无论哪种方式,您都可以在curl命令行中包含构造的JSON,如下所示:

curl ... -d "$(jo or jq command goes here)"
jc3wubiy

jc3wubiy2#

这样的JSON不要手工生成,可以使用jq这样的工具来生成。

#!/bin/bash

stringVar="helloWorldFunction() {\n echo \"hello world\" \n}"

jq -n --arg s "$stringVar" '{name: "my-project", files: [{data: $s}]}' |
  curl -i -H "Authorization: Bearer <MY_API_TOKEN>" \
          -H "Content-Type: application/json" \ 
          -H "Accept: application/json" \
          -X POST  \
          -d @- \
          'https://api.example.com/v1/endpoint'
vmdwslir

vmdwslir3#

就像这样:

#!/bin/bash

stringVar="..."

curl -i -H "Authorization: Bearer <MY_API_TOKEN>" \
    -H "Content-Type: application/json" \
    -H "Accept: application/json" -X POST 'https://api.example.com/v1/endpoint' \
    -d@/dev/stdin <<EOF
{
    "name": "my-project",
    "files": [
        {
            "data": $stringVar
        },
    ],
}
EOF

然后,您应该注意在变量中输入的内容,它必须是有效的JSON

sycxhyv7

sycxhyv74#

作为jq * 和 * curl的替代方法,您可以使用xidel生成JSON * 并 * 提交POST请求。
使用命令行选项:

#!/bin/bash

stringVar='helloWorldFunction() {\n echo "hello world" \n}'

xidel -s --variable var="$stringVar" \
  -H "Authorization: Bearer <MY_API_TOKEN>" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json"
  -d '{serialize(
    {"name":"my-project","files":array{{"data":$var}}},
    {"method":"json"}
  )}' \
  "https://api.example.com/v1/endpoint" \
  -e '$raw'

或者使用查询中的x:request()函数:

#!/bin/bash

stringVar='helloWorldFunction() {\n echo "hello world" \n}'

xidel -s --variable var="$stringVar" -e '
  x:request({
    "headers":(
      "Authorization: Bearer <MY_API_TOKEN>",
      "Content-Type: application/json",
      "Accept: application/json"
    ),
    "post":serialize(
      {"name":"my-project","files":array{{"data":$var}}},
      {"method":"json"}
    ),
    "url":"https://api.example.com/v1/endpoint"
  })/raw
'

$raw//raw返回原始输出,如curl。如果API端点返回JSON,则可以使用$json//json解析它。

相关问题