2

I am using powershell (specifically Azure CLI) to get data from a service, add a value to a list and send a patch/post to an URL.

This is the URL to get the list of data:

$uriList = az rest --method get --uri "https://graph.microsoft.com/beta/applications/$objectId" --header "$header" --query spa.redirectUris | ConvertFrom-Json

This returns an array of strings.

['a', 'b', 'c', 'd', 'e']

if ($uriList -notcontains "f") {
    $uriList  += "f"
}

$uriListJSON = $uriList | ConvertTo-Json

Above, I have added "f" to the array and I want to send it to the url as follows:

$body = "{spa:{redirectUris: $uriListJSON}}"

az rest --method patch --uri "https://graph.microsoft.com/beta/applications/$objectId" --headers "$header" --body "$body"

I get an error:

Unable to read JSON request payload. Please ensure Content-Type header is set and payload is of valid JSON format."

Please advice on what I am doing wrong. I outputted uriListJSON to a file and ran it against a json validator and it passed.

When I hardcode everything to a url like

az rest --method patch --uri "https://graph.microsoft.com/beta/applications/$objectId" --headers $header --body "{spa: {redirectUris: ['a', 'b', 'c', 'd', 'e', 'f']}}"

it works like a charm.

arunmmanoharan
  • 2,535
  • 2
  • 29
  • 60

1 Answers1

2

Your from-and-to JSON conversion results in a string with - standards-compliant - embedded double-quoting ("):

PS> ("['a', 'b', 'c', 'd', 'e']" | ConvertFrom-Json) + 'f' | ConvertTo-Json -Compress

["a","b","c","d","e","f"]

Since you're passing the resulting string to an external program - az - the sad reality as of PowerShell 7.2 is that an extra, manual layer of \-escaping of embedded " characters is required in arguments.
This may get fixed in a future version, which may require opt-in. See this answer for details.

Therefore:

$uriListJSON = ("['a', 'b', 'c', 'd', 'e']" | ConvertFrom-Json) + 'f' | ConvertTo-Json -Compress

$body = "{ \`"spa\`": { \`"redirectUris\`": $($uriListJSON -replace '"', '\"') } }"

Note that while it may not be necessary for az, the above uses a strictly standards-compliant JSON string in which the property names of the verbatim part of your JSON string too are "..."-quoted, which requires both escaping for PowerShell (`") and manual \-escaping for the external program; in combination: \`"

mklement0
  • 382,024
  • 64
  • 607
  • 775
  • Thanks for your advice. I tried it. Its not working. This is a screenshot of what I have done so far. https://imgur.com/a/WeTZCQP – arunmmanoharan Dec 05 '21 at 01:22
  • @a2441918, please see my update - I hadn't noticed that the _verbatim_ part of your JSON needs`"..."` quoting and therefore `\ `-escaping too. – mklement0 Dec 05 '21 at 02:01
  • Tried that. Running into a string issue. https://imgur.com/a/qWiJUVc – arunmmanoharan Dec 05 '21 at 02:40
  • @a2441918: Oops! My bad: forgot to escape the embedded `"` _for PowerShell_ as well - please see my update. – mklement0 Dec 05 '21 at 02:43
  • Sorry. Still the issue. https://imgur.com/a/UHqgzJq Do you want me to run any additonal commands to see if the data is in the correct format? – arunmmanoharan Dec 05 '21 at 04:05
  • I think I am testing the code in powershell 5, not 7.1 – arunmmanoharan Dec 05 '21 at 04:12
  • @a2441918 v5 vs. v7.1 shouldn't make a difference. The answer now shows you how to properly pass your JSON string to `az` (double-quoting the property _names_ may not have been necessary, but it certainly should work). You can see how an external program receives it by running `choice /d Y /t 0 /m $body` (which will additionally print `Y,N]?Y`). Since `az` is implemented as a batch file, URLs that contain `&` could break the call, but then you'd see a different error. The problem may be in the _other_ arguments you're passing to `az`, which I can't help you with. – mklement0 Dec 05 '21 at 04:40
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/239831/discussion-between-a2441918-and-mklement0). – arunmmanoharan Dec 05 '21 at 04:42