how to format json string for aws with powershell
You're passing a JSON string to an external program (
aws
)Irrespective of how you constructed that string - directly as a string, or from an object / hashtable via
ConvertTo-Json
- as of PowerShell 7.1 - manual escaping of embedded"
as\"
is required, which, in turn requires escaping the preexisting\
preceding the embedded"
as\\
.Note: None of this should be necessary, but due to a long-standing bug in PowerShell is - see this answer for details.
PowerShell Core 7.2.0-preview.5 now includes experimental feature
PSNativeCommandArgumentPassing
with an attempted fix, but, unfortunately, it looks like it will lack important accommodations for high-profile CLIs on Windows - see this summary from GitHub issue #15143. However, it would fix calls toaws.exe
, the Amazon Web Services CLI.
# The JSON string to be passed as-is.$json = @'[ { "Sensor":"{\"id\":\"880/2021-04-13\",\"attributes\":\"green\",\"Name\":\"SensorGreen\",\"state\":\"SUCCEEDED\"}", "Source":"google.com" }]'@# Up to at least PowerShell 7.1:# Manually perform the required escaping, to work around PowerShell's# broken argument-passing to external programs.# Note:# -replace '\\', '\\' *looks* like a no-op, but replaces each '\' with '\\'$jsonEscaped = $json -replace '\\', '\\' -replace '"', '\"'# Now pass the *escaped* JSON string to the aws CLI:aws events put-events --entries $jsonEscaped --region "eu-central-1"
ConvertTo-Json
is for converting objects in PowerShell, not a string that you have tried to already write in Json. Your $Json
variable produces this.
"[{\"Sensor\":\"{\\\"id\\\":\\\"880/2021-04-13\\\",\\\"attributes\\\":\\\"green\\\",\\\"Name\\\":\\\"SensorGreen\\\",\\\"state\\\":\\\"SUCCEEDED\\\"}\",\"Source\":\"google.com\"}]"
If you want to create the object in PowerShell and convert it to Json, then you can do this.
$RequestObject = [pscustomobject] @{ Sensor = [pscustomobject] @{ id = "880/2021-04-13" attribute = "green" Name = "SensorGreen" state = "SUCCEEDED" } Source = "google.com"}$Json = $RequestObject | ConvertTo-Json -Compressaws events put-events --entries $Json --region "eu-central-1"
Your Json will look like this if you print your variable out.
{"Sensor":{"id":"880/2021-04-13","attribute":"green","Name":"SensorGreen","state":"SUCCEEDED"},"Source":"google.com"}
Which I think is like the Json that the command is expecting. Not entirely sure why you need the strings escaping or the array. Here it is uncompressed.
{ "Sensor": { "id": "880/2021-04-13", "attribute": "green", "Name": "SensorGreen", "state": "SUCCEEDED" }, "Source": "google.com"}
Just noticed the powershell-2.0
tag. If you are using it, then you should do this instead to create your Json.
$Sensor = New-Object psobject -Property @{ id = "880/2021-04-13" attribute = "green" Name = "SensorGreen" state = "SUCCEEDED"}$RequestObject = New-Object psobject -Property @{ Sensor = $Sensor Source = "google.com"}$Json = $RequestObject | ConvertTo-Json -Compress
EDIT
If you absolutely must escape the strings in that way and have a single item array, then you should just pass the Json that you have written in your answer without any further conversion.
$json='[{"Sensor":"{\"id\":\"880/2021-04-13\",\"attributes\":\"green\",\"Name\":\"SensorGreen\",\"state\":\"SUCCEEDED\"}","Source":"google.com"}]'
If you want to make PowerShell do that for you then you would need to perform some string replacement on the Sensor object first.
PowerShell 2.0
$Sensor = New-Object psobject -Property @{ id = "880/2021-04-13" attribute = "green" Name = "SensorGreen" state = "SUCCEEDED"} $SensorJson = $Sensor | ConvertTo-Json -Compress$SensorJson.Replace("`"","\`"")$RequestObject = New-Object psobject -Property @{ Sensor = $SensorJson Source = "google.com"}$Json = $RequestObject | ConvertTo-Json -Compress
PowerShell 3.0+
$Sensor = [pscustomobject] @{ id = "880/2021-04-13" attribute = "green" Name = "SensorGreen" state = "SUCCEEDED"}$SensorJson = $Sensor | ConvertTo-Json -Compress$SensorJson.Replace("`"","\`"")$RequestObject = [pscustomobject] @{ Sensor = $SensorJson Source = "google.com"}$Json = $RequestObject | ConvertTo-Json -Compress
Then your AWS command
# Add the array around the compressed Json string.aws events put-events --entries "[$Json]" --region "eu-central-1"
"[$Json]"
prints
[{"Sensor":"{\"id\":\"880/2021-04-13\",\"attribute\":\"green\",\"Name\":\"SensorGreen\",\"state\":\"SUCCEEDED\"}","Source":"google.com"}]