补充 Ansgar Wiecher's elegant answer 与背景信息:
让我们定义示例输入,模拟单个嵌套对象,通过ConvertFrom-Json 转换为 PowerShell [pscustomobject] 实例:
$objFromJson = [pscustomobject] @{
Object1 = [pscustomobject] @{key1='o11'; key2='o12'; key3='o13'; key4='o14'}
Object2 = [pscustomobject] @{key1='o21'; key2='o22'; key3='o23'; key4='o24'}
Object3 = [pscustomobject] @{key1='o31'; key2='o32'; key3='o33'; key4='o34'}
Object4 = [pscustomobject] @{key1='o41'; key2='o42'; key3='o43'; key4='o44'}
Object5 = [pscustomobject] @{key1='o51'; key2='o52'; key3='o53'; key4='o54'}
}
输出$objFromJson 给出的输出格式与问题中的一样。
为什么这会导致问题中显示的输出格式?
对于诸如[pscustomobject] 之类的类型,它们没有 有explicit formatting definitions defined for them(通过*.ps1xml 文件并隐式加载到会话中或通过Update-FormatData 显式加载),PowerShell 决定什么默认格式根据类型的属性数量使用:
- 具有最多 4 个属性的类型隐式使用
Format-Table
- 具有 5 个或更多属性的类型隐式使用
Format-List
问题中的示例输入大概是删节;如果真的只有 4 个属性,就会产生 表格 显示。
属性本身是通过在它们的值上调用.PSObject.ToString() 来呈现的,这通常与您在 double- 中引用对象时得到的表示相同带引号的字符串,除了后者总是使用文化-不变 格式,而.ToString() 将尊重当前文化,如果类型支持的话。
在[pscustomobject] 实例的情况下,这会产生一个类似于哈希表文字的表示,但不是一个(有关背景信息,请参阅this answer);例如:
PS> $objFromJson.Object1.PSObject.ToString()
@{key1=o11; key2=o12; key3=o13; key4=o14}
根据需要重塑数据:
无法直接使用诸如Format-Table之类的格式化cmdlet来产生所需的输出-必须首先重新调整数据:
具体来说,对象$objFromJson 的属性必须重新整形为一个自定义对象的集合:
通过 PowerShell 向所有对象添加(以及其他)隐藏的 .PSObject 属性有助于提取 $objFromJson 的属性,其自己的 .Properties 属性包含所有对象属性的集合定义(名称、值、附加元数据,例如属性类型,...);例如:
PS> $objFromJson.Object1.PSObject.Properties
MemberType : NoteProperty
IsSettable : True
IsGettable : True
Value : o11
TypeNameOfValue : System.String
Name : key1
IsInstance : True
# ... remaining properties
输出$objFromJson 的属性定义的集合 并仅提取定义的Name 和Value 属性是朝着正确方向迈出的一步:
PS> $objFromJson.PSObject.Properties | Select-Object Name, Value
Name Value
---- -----
Object1 @{key1=o11; key2=o12; key3=o13; key4=o14}
Object2 @{key1=o21; key2=o22; key3=o23; key4=o24}
Object3 @{key1=o31; key2=o32; key3=o33; key4=o34}
Object4 @{key1=o41; key2=o42; key3=o43; key4=o44}
Object5 @{key1=o51; key2=o52; key3=o53; key4=o54}
但是,我们必须使输出对象的.Value 属性直接属性 的属性才能获得具有属性个体值的输出。
Ansgar 的优雅回答演示了如何在单个管道中做到这一点。
让我用一个从它派生的可重用的辅助函数来补充它:
function ConvertTo-Collection($InputObject) {
foreach ($obj in $InputObject) {
foreach ($prop in $obj.PSObject.Properties) {
$prop.Value | Select-Object @{ n='Name'; e={ $prop.Name }}, *
}
}
}
使用该功能,现在可以实现所需的输出:
ConvertTo-Collection $objFromJson | Format-Table
排除特定属性,例如key3:
ConvertTo-Collection $objFromJson | Select-Object -ExcludeProperty key3 |
Format-Table