Bash脚本:在curl JSON Post数据中使用字符串变量

时间:2022-10-09 15:42:06

I want to send a json request and embedd a variable in the post data. I did a little research and I came up with the single quotes around the variable.

我想发送一个json请求并在post数据中嵌入一个变量。我做了一点研究,我想出了变量周围的单引号。

    #!/bin/bash
    FILENAME="/media/file.avi"
    curl -i -X POST -H "Content-Type: application/json" —d '{"jsonrpc": "2.0", "method": "Player.Open", "params":{"item":{"file":"'$FILENAME'"}}}' http://192.167.0.13/jsonrpc

Unfortunately I get some errors:

不幸的是我收到一些错误:

curl: (6) Couldn't resolve host '—d'
curl: (3) [globbing] nested braces not supported at pos 54
HTTP/1.1 200 OK
Content-Length: 76
Content-Type: application/json
Date: Wed, 29 Jan 2014 19:16:56 GMT

{"error":{"code":-32700,"message":"Parse error."},"id":null,"jsonrpc":"2.0"}

Appearently there are some problems with the braces and the http answer states, that the command could not be executed. What's wrong with my code here? Thanks!

显然,大括号和http应答状态存在一些问题,即命令无法执行。这里的代码出了什么问题?谢谢!

This is my curl version:

这是我的卷曲版本:

curl 7.30.0 (mips-unknown-linux-gnu) libcurl/7.30.0 OpenSSL/0.9.8y
Protocols: file ftp ftps http https imap imaps pop3 pop3s rtsp smtp smtps tftp 
Features: IPv6 Largefile NTLM NTLM_WB SSL 

3 个解决方案

#1


20  

Update: use the simpler

更新:使用更简单

request_body=$(cat <<EOF
{
  "jsonrpc": "2.0",
  "method": "Player.Open",
  "params": {
    "item": {
      "file": "$FILENAME"
    }
  }
}
EOF
)

rather than what I explain below. However, if it is an option, use jq to generate the JSON instead. This ensures that the value of $FILENAME is properly quoted.

而不是我在下面解释的。但是,如果它是一个选项,请使用jq来生成JSON。这可确保正确引用$ FILENAME的值。

request_body=$(jq -n --arg fname "$FILENAME" '
{
  jsonrpc: "2.0",
  method: "Player.Open",
  params: {item: {file: $fname}}
}'

It would be simpler to define a variable with the contents of the request body first:

首先使用请求体的内容定义变量会更简单:

#!/bin/bash
header="Content-Type: application/json"
FILENAME="/media/file.avi"
request_body=$(< <(cat <<EOF
{
  "jsonrpc": "2.0",
  "method": "Player.Open",
  "params": {
    "item": {
      "file": "$FILENAME"
    }
  }
}
EOF
))
curl -i -X POST -H "$header" -d "$request_body" http://192.167.0.13/jsonrpc

This definition might require an explanation to understand, but note two big benefits:

这个定义可能需要解释才能理解,但请注意两个很大的好处:

  1. You eliminate a level of quoting
  2. 你消除了一定程度的报价
  3. You can easily format the text for readability.
  4. 您可以轻松地格式化文本以便于阅读。

First, you have a simple command substitution that reads from a file:

首先,您有一个从文件中读取的简单命令替换:

$( < ... )   # bash improvement over $( cat ... )

Instead of a file name, though, you specify a process substitution, in which the output of a command is used as if it were the body of a file.

但是,您可以指定一个进程替换,而不是文件名,在该替换中,命令的输出就像它是文件的主体一样。

The command in the process substitution is simply cat, which reads from a here document. It is the here document that contains your request body.

进程替换中的命令只是cat,它从here文档中读取。这是包含您的请求正文的here文档。

#2


6  

My suggestion:

我的建议:

#!/bin/bash
FILENAME="/media/file 2.avi"
curl -i -X POST -H "Content-Type: application/json" -d '{"jsonrpc": "2.0", "method": "Player.Open", "params":{"item":{"file":"'"$FILENAME"'"}}}' http://192.167.0.13/jsonrpc

The differences are hyphen in -d (instead of a dash) and double quotes around $FILENAME.

差异是-d(而不是短划线)中的连字符和$ FILENAME周围的双引号。

#3


1  

Here is another way to insert data from a file into a JSON property. This solution is based on a really cool command called jq.

这是将文件中的数据插入JSON属性的另一种方法。这个解决方案基于一个名为jq的非常酷的命令。

Below is an example which prepares request JSON data, used to create a CoreOS droplet on Digital Ocean:

下面是一个准备请求JSON数据的示例,用于在Digital Ocean上创建CoreOS droplet:

# Load the cloud config to variable
user_data=$(cat config/cloud-config)

# Prepare the request data 
request_data='{
  "name": "server name",
  "region": "fra1",
  "size": "512mb",
  "image": "coreos-stable",
  "backups": false,
  "ipv6": true,
  "user_data": "---this content will be replaced---",
  "ssh_keys": [1234, 2345]
}'

# Insert data from file into the user_data property
request_data=$(echo $request_data | jq ". + {user_data: \"$user_data\"}")

#1


20  

Update: use the simpler

更新:使用更简单

request_body=$(cat <<EOF
{
  "jsonrpc": "2.0",
  "method": "Player.Open",
  "params": {
    "item": {
      "file": "$FILENAME"
    }
  }
}
EOF
)

rather than what I explain below. However, if it is an option, use jq to generate the JSON instead. This ensures that the value of $FILENAME is properly quoted.

而不是我在下面解释的。但是,如果它是一个选项,请使用jq来生成JSON。这可确保正确引用$ FILENAME的值。

request_body=$(jq -n --arg fname "$FILENAME" '
{
  jsonrpc: "2.0",
  method: "Player.Open",
  params: {item: {file: $fname}}
}'

It would be simpler to define a variable with the contents of the request body first:

首先使用请求体的内容定义变量会更简单:

#!/bin/bash
header="Content-Type: application/json"
FILENAME="/media/file.avi"
request_body=$(< <(cat <<EOF
{
  "jsonrpc": "2.0",
  "method": "Player.Open",
  "params": {
    "item": {
      "file": "$FILENAME"
    }
  }
}
EOF
))
curl -i -X POST -H "$header" -d "$request_body" http://192.167.0.13/jsonrpc

This definition might require an explanation to understand, but note two big benefits:

这个定义可能需要解释才能理解,但请注意两个很大的好处:

  1. You eliminate a level of quoting
  2. 你消除了一定程度的报价
  3. You can easily format the text for readability.
  4. 您可以轻松地格式化文本以便于阅读。

First, you have a simple command substitution that reads from a file:

首先,您有一个从文件中读取的简单命令替换:

$( < ... )   # bash improvement over $( cat ... )

Instead of a file name, though, you specify a process substitution, in which the output of a command is used as if it were the body of a file.

但是,您可以指定一个进程替换,而不是文件名,在该替换中,命令的输出就像它是文件的主体一样。

The command in the process substitution is simply cat, which reads from a here document. It is the here document that contains your request body.

进程替换中的命令只是cat,它从here文档中读取。这是包含您的请求正文的here文档。

#2


6  

My suggestion:

我的建议:

#!/bin/bash
FILENAME="/media/file 2.avi"
curl -i -X POST -H "Content-Type: application/json" -d '{"jsonrpc": "2.0", "method": "Player.Open", "params":{"item":{"file":"'"$FILENAME"'"}}}' http://192.167.0.13/jsonrpc

The differences are hyphen in -d (instead of a dash) and double quotes around $FILENAME.

差异是-d(而不是短划线)中的连字符和$ FILENAME周围的双引号。

#3


1  

Here is another way to insert data from a file into a JSON property. This solution is based on a really cool command called jq.

这是将文件中的数据插入JSON属性的另一种方法。这个解决方案基于一个名为jq的非常酷的命令。

Below is an example which prepares request JSON data, used to create a CoreOS droplet on Digital Ocean:

下面是一个准备请求JSON数据的示例,用于在Digital Ocean上创建CoreOS droplet:

# Load the cloud config to variable
user_data=$(cat config/cloud-config)

# Prepare the request data 
request_data='{
  "name": "server name",
  "region": "fra1",
  "size": "512mb",
  "image": "coreos-stable",
  "backups": false,
  "ipv6": true,
  "user_data": "---this content will be replaced---",
  "ssh_keys": [1234, 2345]
}'

# Insert data from file into the user_data property
request_data=$(echo $request_data | jq ". + {user_data: \"$user_data\"}")