Wer schonmal ein wenig mit PowerShell und APIs herumexperimentiert hat, kommt um Invoke-RestMethod kaum herum. Mit diesem Befehl lassen sich APIs abfragen, z.B. auch die interne Matrix42-API. Aber mit deutschen Umlauten oder auch anderen Sonderzeichen, wie etwa den ukrainischen oder kyrillischen, gibt es Probleme. Denn wenn man versucht im JSON-Body diese an eine API zu senden, gibt es beispielsweise folgenden Fehler:
Invoke-RestMethod : {"status_code":400,"error_message":"Parsing error.","error_id":2000,"error_data":"JSON parse error - 'utf-8' codec can't decode byte 0xed in
position 91: invalid continuation byte"}
In C:\Program Files (x86)\PSTesting\ForceApiError.ps1:50 Zeichen:18
+ ... onseOrder = Invoke-RestMethod ('https://mein.api.server/api/v0/ ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-RestMethod], WebException
+ FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand
Invoke-RestMethod : {"status_code":400,"error_message":"Parsing error.","error_id":2000,"error_data":"JSON parse error - Expecting value: line 3 column 20 (char 23)"}
In C:\Program Files (x86)\PSTesting\ForceApiError.ps1:61 Zeichen:19
+ ... nseUpdate = Invoke-RestMethod ('https://mein.api.server/api/v0/ ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-RestMethod], WebException
+ FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand
Code-Sprache: PowerShell (powershell)
Das Problem hierbei ist, dass PowerShell oder genauer gesagt die Methode Invoke-Restmehtod seine Dekodierung auf den Wert der Eigenschaft “HttpWebResponse.CharacterSet” stützt. Wenn diese nicht festgelegt ist, verwendet es standardmäßig die Standardkodierung ISO-8859-1. Zumindest wird das hier so diskutiert, aber es könnte meiner Meinung nach auch ganz einfach der Standard-Zeichensatz in der PowerShell-ISE Schuld sein.
Lösung
Was auch immer die Ursache ist, die Lösung ist relativ einfach, oder eigentlich eher nicht 😉
Damit die Sonderzeichen gültig übermittelt werden, man muss den gesamten JSON-Body in einen gültigen Zeichensatz konvertieren, also in unserem Fall UTF-8. In PowerShell funktioniert das folgendermaßen, unter der Annahme, dass dein JSON-Body den du an die API senden willst in der Variable $body steht:
$headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$headers.Add("Authorization", "Bearer XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.XXXXXXXXXX-XXXXXXXXXXXXXX")
$headers.Add("Content-Type", "application/json")
$body = "{
`n `"Subject`": `"Betreff im Json Body`",
`n `"Description`": `"Beschreibung `",
`n `"Urgency`": 1
`n}"
$defaultEncoding = [System.Text.Encoding]::GetEncoding('ISO-8859-1')
$utf8Bytes = [System.Text.Encoding]::UTf8.GetBytes($body)
$bodydecoded = $defaultEncoding.GetString($utf8bytes)
$response = Invoke-RestMethod ('https://mein.api.server/api/v0/dosomething) -Method 'PUT' -Headers $headers -Body $bodydecoded
$response | ConvertTo-Json
Code-Sprache: PowerShell (powershell)
Sobald du diesen konvertierten JSON-Body sendest, werden alle Zeichen korrekt übermittelt. Das Gemeine an diesem Fehler ist natürlich, dass er erst auftritt, wenn man mal Sonderzeichen in der Variable hat… und wer testet schon mit Sonderzeichen 😀