Ryan Arnold Ryan Arnold - 9 months ago 63
JSON Question

Powershell & Curl - Using variables inside single-quoted JSON body

I am currently trying to automate new user creation in our Zendesk ticketing system using Powershell and Curl. The problem I am running into is that the curl json body is enclosed by single quotes and I need to reference a variable inside that body. Here is what I have:

$Firstname = "Test"
$Lastname = "User"
$email= 'user@test.org'
curl.exe https://mydomain.zendesk.com/api/v2/users.json -H "Content-Type: application/json" -X POST -d '{\"user\": {\"name\": \"$Firstname $Lastname\", \"email\": \"$email\"}}' -v -u myuser:mypass

This works fine if I type in regular text values inside the json, but how can I get it to recognize the variables $Firstname, $Lastname and $email?

Answer Source

Try the following:

$Firstname = "Test"
$Lastname = "User"
$email= 'user@test.org'   
{\"user\": {\"name\": \"$Firstname $Lastname\", \"email\": \"$email\"}}
curl.exe https://mydomain.zendesk.com/api/v2/users.json -d $json -H 'Content-Type: application/json' -X POST -v -u myuser:mypass

Using a double-quoted here-string @"..." makes specifying embedded " instances easy (no escaping required), while still expanding variable references - see the docs online or Get-Help about_Quoting_Rules.

If you wanted to do it inline with a regular double-quoted string, you'll have to escape the " instances for PowerShell too (as `"):

"{\`"user\`": {\`"name\`": \`"$Firstname $Lastname\`", \`"email\`": \`"$email\`"}}"

You're clearly aware of the additional need to \-escape the " instances, but just to explain why that is needed:

PowerShell, after its own parsing and interpolation, wraps the resulting string in double quotes when passing it to an external program (curl, in this case).

Thus, any embedded double quotes must be properly escaped for the target program; for Unix-heritage programs such as curl, embedded " instances must be escaped as \".


Ryan himself points out in a comment that using a hashtable to construct the data and then converting it to JSON with ConvertTo-Json and feeding it to curl via stdin is an alternative that avoids the quoting headaches:

# Create data as PS hashtable literal.
$data = @{ user = @{ name = "$Firstname $Lastname"; email = "$adUsername@mydomain.org" } }

# Convert to JSON with ConvertTo-Json and pipe to `curl` via *stdin* (-d '@-')
$data | ConvertTo-Json -Compress | curl.exe mydomain.zendesk.com/api/v2/users.json -d '@-' -H "Content-Type: application/json" -X POST -v -u myuser:mypass