Reputation: 317
I have a array list of PSCustomObjects that I can output with Format-Table and looks like expected.
Name Property1 Property2 Property3
---- --------- --------- ---------
name1 value1 value2 value3
Now it happens, that one property of the PSCustomObject needs to hold two (or more) values, so I decided to follow an object-oriented approach and change that property to a PSCustomObject also, ending up in a list of objects containing objects, then the output looks like this:
Name Property1 Property2 Property3
---- --------- --------- ---------
name1 value1 @{Sub1=valueX; Sub2=valueY} value3
What I am searching for is some sort of recursively output of Format-Table, which expands the object inside, to look something like this:
Name Property1 Sub1 Sub2 Property3
---- --------- ---- ---- ---------
name1 value1 valueX valueY value3
Is this possible anyhow? Or do I have to fallback to "normal" lists when building up that object list?
thank you!
Upvotes: 0
Views: 1518
Reputation: 174485
All you need to do recursively is discover that "paths" to the leaf values and then generate property expression selectors for them:
function Format-FlatTable {
[CmdletBinding()]
param(
[Parameter(ValueFromPipeline=$true)]
[psobject]$InputObject
)
begin {
function Get-FlatSelector {
param(
[psobject]$Object,
[string]$Prefix
)
# Enumerate all properties
$object.psobject.Properties |ForEach-Object {
# Nested custom object, let's recurse
if($_.Value -is [System.Management.Automation.PSCustomObject]){
Get-FlatSelector $_.Value -Prefix $_.Name
}
else {
if($prefix){
# We're not at the root level anymore, construct a property expression table
@{Name="$prefix.$($_.Name)";Expression=[scriptblock]::Create("`$_.$prefix.$($_.Name)")}
}
else{
# Still at the root level, we can select value properties by name alone
$_.Name
}
}
}
}
}
process
{
# Use the first input object to determine how to flatten
$selectors = Get-FlatSelector $InputObject[0]
# Use `Format-Table` to only select flattened property values
$InputObject |Format-Table $selectors
}
}
Which would produce a table format like the one you want, but without any naming collisions:
[pscustomobject]@{
Name='Name1'
Property1 = 'value1'
Property2 = [pscustomobject]@{
Sub1 = 'valueX'
Sub2 = 'ValueY'
}
Property3 = 'value3'
} |Format-FlatTable
Output:
Name Property1 Property2.Sub1 Property2.Sub2 Property3
---- --------- -------------- -------------- ---------
Name1 value1 valueX ValueY value3
Upvotes: 3