I'm trying to send a post request using az rest. When I try send request like this - it works:
az rest --method POST --uri "https://someaddress" --body '{"some": "Text" }'
but If I put ')' - closing parenthesis in body like this:
az rest --method POST --uri "https://someaddress" --body '{"some": "Text)" }'
then my rest body is cut off and I receive an error:
az : " }" was unexpected at this time.
At line:2 char:1
+ az rest --method POST --uri "https://someaddress" --body '{"some": "T ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (" }" was unexpected at this time.:String) [], RemoteException
+ FullyQualifiedErrorId : NativeCommandError
How can I escape the ')' character?
Let me complement your own answer with some background information:
'{ "some": "Text)" }'
is a valid JSON string (verify with {"some": "Text)" } | ConvertFrom-Json
) and therefore should work.
However, due to a long-standing bug in how PowerShell passes arguments with embedded "
chars. to external programs (such as the az
CLI), present up to PowerShell 7.2.x, "
must manually be escaped - typically as \"
, alternatively (if supported by the target program) as ""
; for select target programs - including the case at hand - this manual escaping continues to be required in PowerShell 7.3+ (details below).
As a result of the bug, embedded "
chars. are in effect removed:
'{ "some": "Text)" }'
becomes "{ "some": "Text)" }"
behind the scenes, which most CLIs, including az
, parse as verbatim { some: Text) }
, because - due to lack of escaping of the embedded "
- all "
instances are considered to have syntactic function and are therefore removed.
See this answer for details.
You can use az --debug
to echo how az
parses its arguments, which demonstrates the problem:
# Note the effective loss of the " chars. in the output.
PS> (az --debug '{ "foo": "bar" }' 2>&1) | Select-String 'command arguments'
DEBUG: cli.knack.cli: Command arguments: ['--debug', '{ foo: bar }']
In fact, there's a dedicated Quoting issues with PowerShell article that az rest
Azure docs link to that discusses the problems, which not only affect embedded "
chars. but also (space-less) URLs that contain &
(e.g. https://example.org?foo&bar
).
The problem with &
is owed to the fact that az
is implemented as a batch file - az.cmd
. It is also the reason ""
rather than \"
must be used for manual escaping for robust operation (\"
being the most widely used syntax for escaping, with only Windows-heritage CLIs also / exclusively supporting ""
), because cmd.exe
(the batch-file interpreter) recognizes only ""
as an escaped "
, so that an argument on its process command line such as "{ \"some\": \"Text)\" }"
breaks an az.cmd
call, because the )
is seen as unquoted, i.e. as having syntactic function, which cause a syntax error in cmd.exe
. By contrast, "{ ""some"": ""Text)"" }"
works.
Therefore you have two options:
Perform the required manual escaping - note the ""
:
# Direct:
az rest --method POST --uri "https://someaddress" --body '{ ""some"": ""Text)"" }'
# Indirect, using string replacement:
az rest --method POST --uri "https://someaddress" --body '{ "some": "Text)" }'.Replace('"', '""')
az
is a batch file (az.cmd
) and because the $PSNativeCommandArgumentPassing
preference variable defaults to Windows
mode - in which the old broken behavior is selectively retained, notably also for batch files - the above works by default in PowerShell 7.3+ as well.If your target web service supports it, bypass the problem by switching to '
-quoting (single quotes), as also shown in your answer, which isn't affected by the PowerShell bug:
az rest --method POST --uri "https://someaddress" --body "{ some: 'Text)' }"
Note that the above is - strictly speaking - not valid JSON, but some JSON parsers also accept JSON-like strings, allowing the property names to be unquoted (some
) and allowing use of single-quoting in string property values (and also names, if needed) in lieu of the JSON-standard double-quoting.
Json.NET
parser that underlies PowerShell's ConvertFrom-Json
as of PowerShell 7.3.3."{ some: 'Text)' }" | ConvertFrom-Json
works, for instance).System.Text.Json
APIs ([System.Text.Json.JsonDocument]::Parse("{ some: 'Text)' }")
breaks, for instance)The fact that you say '{"some": "Text" }'
- with no )
- worked even suggests that your service's JSON parser also accepts string property values with no quoting, given that az
saw this arguments as verbatim {some: Text }
'{"some": "Text)" }'
- with )
- which PowerShell (brokenly) placed as"{"some": "Text)" }"
on the az
process command line - caused the batch file that the az
is implemented as - az.cmd
- to break, because to cmd.exe
(the interpreter of batch files), the )
is then unquoted (outside a "..."
string), which means it has syntactic function, ultimately causing the syntax error you saw (… was unexpected at this time
).