There are different ways to represent (display) an object in PowerShell but when it comes to complex objects it is either very verbose or quiet useless:
$Object = @{ 'a' = 1; 'b' = 2 }
Just outputting (Format-Host, or Format-List) returns a multiline output, as:
$Object
Name Value
---- -----
a 1
b 2
Converting it to a string "$Object" or $Object.ToString() doesn't reveal anything about its contents:
System.Collections.Hashtable
Converting it to Json $Object |ConvertTo-Json -Compress, gets close to what I would like to see (but a little too expressive cmdlet for what I need):
{"a":1,"b":2}
I wonder whether there is a way access the representation formatting used by PowerShell display cmdlets, as e.g. the value behind the ImmediateBaseObject and BaseObject:
$Object.PSObject
Members : {System.Object Item(System.Object key) {get;set;}, bool IsReadOnly {get;}, bool IsFixedSize {get;}, bool IsSynchronized {get;}…}
Properties : {bool IsReadOnly {get;}, bool IsFixedSize {get;}, bool IsSynchronized {get;}, System.Collections.ICollection Keys {get;}…}
Methods : {Add, Clear, Clone, Contains…}
ImmediateBaseObject : {[a, 1], [b, 2]} # <-- This representation
BaseObject : {[a, 1], [b, 2]} #
TypeNames : {System.Collections.Hashtable, System.Object}
Wishful thinking, I would like to be able to do something like this:
[PowerShellFormat]$Object
And get the same formatting back for any (complex) object as shown behind BaseObject for $Object.PSObject.
As for this case:
{[a, 1], [b, 2]}
JosefZ has provided the crucial pointer:
Call
.GetEnumerator()on your dictionary in order to enumerate its entries, which are key-value pairs, such as of type[System.Collections.DictionaryEntry]inhashtableinstances.Unlike dictionaries as a whole, their entries stringify meaningfully, in the form
[<key>, <value>]- though it's important to note that this is just a for-display representation, not suitable for programmatic processing.When PowerShell's formatting system stringifies a dictionary stored in a property of an input object, it treats it as an array of entries, and stringifies that array similarly to how arrays are stringified in expandable strings:
The difference is that the whole representation is enclosed in
{...}and that the (stringified) elements are separated with,. You saw this in the display formatting of@{ 'a' = 1; 'b' = 2 }.psobject(.ImmediateBaseObjectand.BaseObjectproperties).I'm not aware of a public method that would produce this format, but it isn't hard to produce it yourself:
Note:
The
.GetEnumerator()call must be wrapped in@(...)to force actual enumeration, resulting in an array.It follows that you can use the above for arrays as inputs too.
Getting an analogous string representation or
[pscustomobject]instances is much simpler: Use string interpolation, i.e. embed the object in an expandable (double-quoted) string ("..."):Note:
Unlike hashtables/dictionaries,
[pscsutomobject]instances stringify the same way in expandable strings and as properties of formatted object representations.Note the difference in formats compared to the hashtable visualization, with the property name-value pairs separate with
=(and no whitespace), multiple properties separated with;, and@{as the opening delimiter.Curiously, this format is very similar to the syntax of a hashtable literal.
Finally, just to demonstrate that PowerShell's formatting system indeed produces the representations above for hashtables and
[pscustomobject]instances used as properties:Output: