How to Convert a String to a Hashtable in PowerShell (and Back)

To convert a string to a hashtable in PowerShell, use ConvertFrom-StringData. It reads text with one key=value pair per line and returns a hashtable:

$text = @'
Name = Emma Carter
Office = Seattle
Role = Finance Manager
'@

$user = ConvertFrom-StringData -StringData $text
"Type:   $($user.GetType().Name)"
"Name:   $($user.Name)"
"Office: $($user['Office'])"

Output:

Type:   Hashtable
Name:   Emma Carter
Office: Seattle

Below I handle one-line strings, backslashes, JSON and value types, then go the other way and turn a hashtable back into a string. Every example ran in PowerShell 7.6 and Windows PowerShell 5.1 unless I say otherwise.

Convert a one-line key=value string

ConvertFrom-StringData needs each pair on its own line. For a string like Server=web01;Port=443, replace the semicolons with new lines first:

$line = 'Server=web01;Port=443;Region=us-west'

$settings = ConvertFrom-StringData -StringData ($line -replace ';', "`n")
$settings.GetEnumerator() | Sort-Object -Property Name | ForEach-Object { '{0,-7} = {1}' -f $_.Name, $_.Value }

Output:

Port    = 443
Region  = us-west
Server  = web01
PowerShell convert a key value string to a hashtable
A semicolon-separated string becomes a hashtable with three keys (PowerShell 7)

Hashtables don’t keep the original order, so I sorted the keys for display. PowerShell 7 also has a -Delimiter parameter for pairs separated by something other than =.

Every value is a string

ConvertFrom-StringData doesn’t guess types. Numbers and True/False come back as text, so convert them before you do math or comparisons:

$settings = ConvertFrom-StringData -StringData "Port=443`nEnabled=true"

"Port is a $($settings.Port.GetType().Name), Enabled is a $($settings.Enabled.GetType().Name)"
$port = [int]$settings.Port
$enabled = [System.Convert]::ToBoolean($settings.Enabled)
"After converting: $($port.GetType().Name) $port, $($enabled.GetType().Name) $enabled"

Output:

Port is a String, Enabled is a String
After converting: Int32 443, Boolean True

Converting strings to Booleans explains why ToBoolean is safer than a [bool] cast here.

Backslashes need doubling

ConvertFrom-StringData treats a backslash as the start of an escape sequence, like \n. A Windows path such as C:\Logs fails, because \L isn’t a valid sequence:

$paths = ConvertFrom-StringData -StringData "LogPath=C:\\Logs\\app"
"Doubled backslashes: $($paths.LogPath)"

try {
    $bad = ConvertFrom-StringData -StringData 'LogPath=C:\Logs\app'
    "Single backslashes:  $($bad.LogPath)"
}
catch { 'Single backslashes:  Failed. \L is not a valid escape sequence' }

Output:

Doubled backslashes: C:\Logs\app
Single backslashes:  Failed. \L is not a valid escape sequence
PowerShell ConvertFrom-StringData backslash escape error with Windows paths
Doubled backslashes work, while single ones fail on \L (Windows PowerShell 5.1)

For text you read from a file, double them with -replace before converting. In the pattern, \\ matches one backslash, and in the replacement it writes two:

$line = 'LogPath=C:\Logs\app'
$escaped = $line -replace '\\', '\\'

"Escaped text: $escaped"
"Value:        $((ConvertFrom-StringData -StringData $escaped).LogPath)"

Output:

Escaped text: LogPath=C:\\Logs\\app
Value:        C:\Logs\app

Microsoft covers the escape rules in the ConvertFrom-StringData documentation.

Convert a JSON string to a hashtable

For JSON, PowerShell 7 has ConvertFrom-Json -AsHashtable. It handles nested arrays too, and in PowerShell 7.6 it returns an OrderedHashtable, which keeps the JSON key order:

$json = '{ "Name": "Emma Carter", "Office": "Seattle", "Groups": ["Sales", "VPN Users"] }'

$user = $json | ConvertFrom-Json -AsHashtable
"Type: $($user.GetType().Name)"
"Groups: $($user.Groups -join ', ')"

Output:

Type: OrderedHashtable
Groups: Sales, VPN Users

Windows PowerShell 5.1 has no -AsHashtable. Convert to an object first, then copy each property into a hashtable:

$json = '{ "Name": "Emma Carter", "Office": "Seattle" }'

$object = $json | ConvertFrom-Json
$user = @{}
foreach ($p in $object.PSObject.Properties) { $user[$p.Name] = $p.Value }
"Type: $($user.GetType().Name), Name: $($user.Name), Office: $($user.Office)"

Output:

Type: Hashtable, Name: Emma Carter, Office: Seattle

The ConvertFrom-Json documentation covers -AsHashtable and -Depth.

Convert a hashtable to a string

Putting a hashtable straight into a string gives only its type name. Join the pairs yourself, or use ConvertTo-Json for a compact one-line version:

$user = [ordered]@{ Name = 'Emma Carter'; Office = 'Seattle'; Role = 'Finance Manager' }

"Plain string:   $user"
"key=value list: $(($user.GetEnumerator() | ForEach-Object { "$($_.Key)=$($_.Value)" }) -join '; ')"
"JSON:           $($user | ConvertTo-Json -Compress)"

Output:

Plain string:   System.Collections.Specialized.OrderedDictionary
key=value list: Name=Emma Carter; Office=Seattle; Role=Finance Manager
JSON:           {"Name":"Emma Carter","Office":"Seattle","Role":"Finance Manager"}
PowerShell convert a hashtable to a string
A plain string shows the type name, while joining pairs or ConvertTo-Json shows the data (PowerShell 7)

The key=value form is easy to read in logs. JSON is better when another script or program needs to read it back.

Out-String for a table

Out-String captures the same table PowerShell shows on screen, as one multi-line string:

$user = [ordered]@{ Name = 'Emma Carter'; Office = 'Seattle' }

$table = $user | Out-String
"Out-String gave $($table.Trim().Split("`n").Count) lines:"
$table.Trim()

Output:

Out-String gave 4 lines:
Name                           Value
----                           -----
Name