Public/Convert-StringEncoding.ps1
Function Convert-StringEncoding { <# .SYNOPSIS Converts a string between different encodings. This is useful e.g. if you have APIs, that deliver UTF8 data, but does not deliver the encoding information, so PowerShell (especially 5.1 and before) is interpreting it in the default encoding which is not always UTF8. .DESCRIPTION Apteco PS Modules - Convert String Encoding Example calls (will create some strange outputs, depending on your configuration, so better look at example below in the source code): Convert-StringEncoding -string "žluťoučký kůň úpěl ďábelské ódy" -inputEncoding "Windows-1252" -outputEncoding "utf-8" Convert-StringEncoding -string "žluťoučký kůň úpěl ďábelské ódy" -inputEncoding ([Console]::OutputEncoding.HeaderName) -outputEncoding ([System.Text.Encoding]::UTF8.HeaderName) Use one of these encodings header names for input and output Especially for Pwsh7 make sure to use the HeaderName of the encoding like "Windows-1252" instead of "iso-8859-1" [System.Text.Encoding]::GetEncodings() More explanation of this function and the background # representation as bytes from this string: žluťoučký kůň úpěl ďábelské ódy # [System.Text.encoding]::UTF8.GetBytes("žluťoučký kůň úpěl ďábelské ódy") -join "," $utf8StringBytesArr = @(197,190,108,117,197,165,111,117,196,141,107,195,189,32,107,197,175,197,136,32,195,186,112,196,155,108,32,196,143,195,161,98,101,108,115,107,195,169,32,195,179,100,121) # Output of original string Write-Host "`nThis is the correct encoding representation of the string:`n$( [System.Text.encoding]::UTF8.GetString($utf8StringBytesArr) )" # Create a wrong encoding representation of the UTF-8 string and output it, be aware default encoding and console encoding diffes in some powershell environments like Pwsh7 $stringDefaultEncoding = [System.Text.encoding]::GetEncoding(([Console]::OutputEncoding.HeaderName)).GetString($utf8StringBytesArr) Write-Host "`nThis is the wrong encoding representation of the string:`n$( $stringDefaultEncoding )" # Convert the string from the default encoding to the original encoding utf8 in this example $stringCorrectEncoding = Convert-StringEncoding -string $stringDefaultEncoding -inputEncoding ([Console]::OutputEncoding.HeaderName) -outputEncoding ([System.Text.Encoding]::UTF8.HeaderName) Write-Host "`nThis is the correct encoding representation of the string after reverse conversion:`n$( $stringCorrectEncoding )" To solve these problems, load the content with Invoke-WebRequest rather than Invoke-RestMethod, and convert the content with the function above # So instead of $response = Invoke-RestMethod -Uri "https://www.example.com/api" # Do this $response = Invoke-WebRequest -Uri "https://www.example.com/api" # Convert data to utf8 encoding $fixedResponse = Convert-StringEncoding -string $response.Content -inputEncoding ([Console]::OutputEncoding.HeaderName) -outputEncoding ([System.Text.Encoding]::UTF8.HeaderName) # Now parse the json or whatever like $json = ConvertFrom-Json -InputObject $fixedResponse $json .PARAMETER String String to change the encoding for .PARAMETER InputEncoding The input encoding like "Windows-1252" or ([Console]::OutputEncoding.HeaderName) as a string .PARAMETER OutputEncoding The output encoding for the string. Default is UTF8 .EXAMPLE Convert-StringEncoding -string "žluťoučký kůň úpěl ďábelské ódy" -inputEncoding "Windows-1252" -outputEncoding "utf-8" .EXAMPLE Convert-StringEncoding -string "žluťoučký kůň úpěl ďábelské ódy" -inputEncoding ([Console]::OutputEncoding.HeaderName) -outputEncoding ([System.Text.Encoding]::UTF8.HeaderName) .EXAMPLE "žluťoučký kůň úpěl ďábelské ódy", "Hellö Wörld" | Convert-StringEncoding -inputEncoding "Windows-1252" -outputEncoding "utf-8" .INPUTS String .OUTPUTS String .NOTES Author: florian.von.bracht@apteco.de #> [CmdletBinding()] param( [Parameter(Mandatory=$true,ValueFromPipeline=$true)][String]$String ,[Parameter(Mandatory=$true)][String]$InputEncoding ,[Parameter(Mandatory=$false)][String]$OutputEncoding = "utf-8" ) Process { # Check input encoding, if wrong it throws an exception [System.Text.Encoding]::GetEncoding($InputEncoding) | Out-Null # Convert the bytes back $bytesArr = [System.Text.Encoding]::GetEncoding($InputEncoding).GetBytes($String) $str = [System.Text.encoding]::GetEncoding($OutputEncoding).GetString($bytesArr) # Return result return $str } } |