how to format json string for aws with powershell how to format json string for aws with powershell json json

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 to aws.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"}]