For \"Get-Msoldomain\" powershell command-let I get the below output (lets call it Output#1) where Name, Status and Authentication are the property names a
Well, if you don't mind to take a little trip :) you can convert it to CSV which will force the string output, then re-convert it back from CSV to PS Object, then finally back to Json.
Like this:
Get-MsolDomain | ConvertTo-Csv | ConvertFrom-Csv | ConvertTo-Json
PowerShell Core offers a simple solution via ConvertTo-Json's -EnumsAsStrings switch.
GetMsolDomain | ConvertTo-Json -EnumsAsStrings # PS *Core* only
Unfortunately, this switch isn't supported in Windows PowerShell.
Avshalom's answer provides a quick workaround that comes with a big caveat, however: All property values are invariably converted to strings in the process, which is generally undesirable (e.g., the Authentication property's numeric value of 0 would turn into string '0').
Here's a more generic workaround based on a filter function that recursively introspects the input objects and outputs ordered hashtables that reflect the input properties with enumeration values converted to strings and all other values passed through, which you can then pass to ConvertTo-Json:
Filter ConvertTo-EnumsAsStrings ([int] $Depth = 2, [int] $CurrDepth = 0) {
if ($_ -is [enum]) { # enum value -> convert to symbolic name as string
$_.ToString()
} elseif ($null -eq $_ -or $_.GetType().IsPrimitive -or $_ -is [string] -or $_ -is [decimal] -or $_ -is [datetime] -or $_ -is [datetimeoffset]) {
$_
} elseif ($_ -is [Collections.IEnumerable]) {
, ($_ | ConvertTo-EnumsAsStrings -Depth $Depth -CurrDepth ($CurrDepth+1))
} else { # non-primitive type -> recurse on properties
if ($CurrDepth -gt $Depth) { # depth exceeded -> return .ToString() representation
"$_"
} else {
$oht = [ordered] @{}
foreach ($prop in $_.psobject.properties) {
if ($prop.Value -is [Collections.IEnumerable] -and -not $prop.Value -is [string]) {
$oht[$prop.Name] = @($prop.Value | ConvertTo-EnumsAsStrings -Depth $Depth -CurrDepth ($CurrDepth+1))
} else {
$oht[$prop.Name] = $prop.Value | ConvertTo-EnumsAsStrings -Depth $Depth -CurrDepth ($CurrDepth+1)
}
}
$oht
}
}
}
Caveat: As with ConvertTo-Json, the recursion depth (-Depth) is limited to 2 by default, to prevent infinite recursion / excessively large output (as you would get with types such as [System.IO.FileInfo] via Get-ChildItem, for instance). Similarly, values that exceed the implied or specified depth are represented by their .ToString() value. Use -Depth explicitly to control the recursion depth.
Example call:
PS> [pscustomobject] @{ p1 = [platformId]::Unix; p2 = 'hi'; p3 = 1; p4 = $true } |
ConvertTo-EnumsAsStrings -Depth 2 |
ConvertTo-Json
{
"p1": "Unix", # Enum value [platformId]::Unix represented as string.
"p2": "hi", # Other types of values were left as-is.
"p3": 1,
"p4": true
}
Note: -Depth 2 isn't necessary here, given that 2 is the default value (and given that the input has depth 0), but it is shown here as a reminder that you may want to control it explicitly.