由Invoke-RestMethod或ConvertFrom-Json返回的格式[pscustomobject]实例

时间:2016-12-11 17:47:54

标签: json powershell formatting output-formatting

我正在尝试从我从RESTful API收到的JSON文件创建一个表。

当我打印json对象的属性时,我得到一个这样的输出:

PS> Write-Output JSON.Object

Object1           : @{key1=property; key2=property; key3=property; key4=property}
Object2           : @{key1=property; key2=property; key3=property; key4=property}
Object3           : @{key1=property; key2=property; key3=property; key4=property}
Object4           : @{key1=property; key2=property; key3=property; key4=property}

我希望看到的输出是:

Name              key1        key2        key3        key4
-----             ----        ----        ----        ----
Object1           property    property    property    property
Object2           property    property    property    property
Object3           property    property    property    property

此外,是否可以避免显示特定的密钥及其属性?

示例:

Name              key1        key2        key4      # ← Not displaying key3
-----             ----        ----        ----
Object1           property    property    property
Object2           property    property    property
Object3           property    property    property

2 个答案:

答案 0 :(得分:4)

您需要将父键名作为属性Name添加到嵌套对象:

$json.Object | ForEach-Object {
  foreach ($p in $_.PSObject.Properties) {
    $p.Value | Select-Object @{n='Name';e={$p.Name}},*
  }
}

请注意,默认情况下,PowerShell将以列表形式呈现输出,因为您的对象具有4个以上的属性。通过Format-List -AutoSize对其进行管道输出以获得表格输出。

答案 1 :(得分:2)

使用背景信息 补充 Ansgar Wiecher's elegant answer

让我们定义样本输入,模拟通过[pscustomobject]转换为PowerShell ConvertFrom-Json实例的单个嵌套对象:

$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文件并隐式加载到会话中或通过{{3}显式加载}),PowerShell根据类型的属性数决定要使用的默认格式:

  • 最多包含4个属性的类型隐式使用Format-Table
  • 具有5个或更多属性的类型隐式使用Format-List

问题中的示例输入大概是删节;如果只有4个属性,则会产生表格显示。

属性本身是通过在其值上调用.PSObject.ToString() 来呈现的,这通常与您引用对象时获得的表示相同在双引号字符串中,除了后者始终使用culture- 不变格式,而.ToString()将尊重当前文化,如果类型支持它。

对于[pscustomobject]实例,这会导致表示类似于哈希表文字,但不是一个(有关背景信息,请参阅{{3} }); e.g:

PS> $objFromJson.Object1.PSObject.ToString()
@{key1=o11; key2=o12; key3=o13; key4=o14}

根据需要重塑数据:

无法直接使用格式化cmdlet(例如Format-Table )来产生所需的输出 - 数据必须首先重新塑造

具体而言,对象$objFromJson的属性必须重新整形为自定义对象的集合

  • Name属性包含给定媒体资源的名称

  • 其他属性是该属性的对象的属性;换句话说:输入属性的属性必须是输出对象本身的属性。

PowerShell为所有对象添加(以及其他)隐藏的$objFromJson属性,便于提取.PSObject的属性,其自身的.Properties属性包含所有对象的集合对象的属性 definitions (名称,值,附加元数据,如属性类型,......); e.g:

PS> $objFromJson.Object1.PSObject.Properties
MemberType      : NoteProperty
IsSettable      : True
IsGettable      : True
Value           : o11
TypeNameOfValue : System.String
Name            : key1
IsInstance      : True
# ... remaining properties

输出$objFromJson 属性定义的集合,并仅提取定义' NameValue属性是朝着正确方向迈出的一步:

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