Zach Smith
Zach Smith

Reputation: 8971

How to include JSON string in cURL command when curl command itself is a string

I have the following string:

barrelRepDoc='{"'"_id"'":"'"push_$systemName"'","'"source"'":"'"$systemName"'","'"target"'":"'"platform2ReplicationTargetBaseURL/$systemName"'","'"create_target"'":true,"'"continuous"'":true,"'"user_ctx"'":{"'"name"'":"'"admin"'","'"roles"'":["'"_admin"'"]},"'"owner"'":"'"admin"'"}'

And I'm passing that string as the -d parameter into a cURL string such as this:

barrelRepcURL="curl -u $username:$password -X POST couchURL/db -H 'Content-Type:application/json' -d '$barrelRepDoc'"

And I'm then executing the command on this line:

barrelRepcURLresponse=$($barrelRepcURL)

And I'm getting invalid JSON. However, if I print out $barrelRepcURL, I get a string that executes as it is supposed to when pasted into the terminal.

I would like feedback on the cURL command, which is why I'm using a string. (echo $barrelRepcURLresponse)

How can I include the barrelRepDoc within the cURL command string and keep valid JSON?

Upvotes: 1

Views: 945

Answers (2)

Tom Fenech
Tom Fenech

Reputation: 74685

Is there any reason you're trying to use a string instead of a function?

This would work:

barrelRepcURL() {
    local username=$1
    local password=$2
    local barrelRepDoc=$3
    curl -u "$username":"$password" -X POST couchURL/db -H 'Content-Type:application/json' -d "$barrelRepDoc"
}

Then just call it like barrelRepcURL user pass "$barrelRepDoc". Obviously you could skip the creation of local variables and just use the positional parameters directly if you wanted.

The response of the curl command will already be printed to the screen so there's no need to store it to a variable just for that. However, it's still possible to use response=$(barrelRepcURL ...) if you want.

You might want to consider using printf to build your JSON variable by the way:

printf -v barrelRepDoc '{"_id":"push_%s","source":"%s","target":"platform2ReplicationTargetBaseURL/%s","create_target":true,"continuous":true,"user_ctx":{"name":"admin","roles":["_admin"]},"owner":"admin"}' "$systemName" "$systemName" "$systemName"

The -v switch can be used to write to a variable. It's still a long line but means that you don't have to bother with as many quotes.

Alternatively, as suggested by chepner in the comments (thanks) you could use a tool such as jq to produce the JSON:

barrelRepDoc=$(jq -n --arg systemName foo '{
    _id: ("push_" + $systemName), 
    source: $systemName, 
    target: ("platform2ReplicationTargetBaseURL/" + $systemName),
    create_target: true, 
    continuous: true, 
    user_ctxa: { name: "admin", roles: ["_admin"] },
    owner: "admin"
}')

In this example, you would replace foo with the value that would be used as $systemName.

Upvotes: 5

glenn jackman
glenn jackman

Reputation: 247062

This is BashFaq50 -- the short answer is to use an array to hold the curl command:

barrelRepDoc='{"_id":"push_'"$systemName"'","source":"'"$systemName"'","target":"platform2ReplicationTargetBaseURL/'"$systemName"'","create_target":true,"continuous":true,"user_ctx":{"name":"admin","roles":["_admin"]},"owner":"admin"}'

barrelRepcURL=( 
    curl -u "$username:$password"
         -X POST
         -H 'Content-Type:application/json' 
         -d "$barrelRepDoc"
            couchURL/db 
)

barrelRepcURLresponse=$( "${barrelRepcURL[@]}" )

Tom has a great answer though. Seriously consider his advice.

Upvotes: 2

Related Questions