Bash script: Use string variable in curl JSON Post data

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.

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. You can easily format the text for readability.

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.


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.


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.

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

# 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\"}")