简体   繁体   English

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

[英]Format [pscustomobject] instances returned by Invoke-RestMethod or ConvertFrom-Json

I am trying to create a table from a JSON file I am receiving from a RESTful API. 我正在尝试从我从RESTful API接收的JSON文件创建一个表。

When I print the property of the json object I get an output like this: 当我打印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}

The output I would like to see is this: 我希望看到的输出是这样的:

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

In addition, is it possible to avoid displaying a specific key and it's properties? 另外,是否可以避免显示特定键及其属性?

Example: 例:

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

You need to add the parent keyname as a property Name to the nested objects: 您需要将父键名作为属性Name到嵌套对象:

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

Note that PowerShell will render the output in list form by default, since your objects have more than 4 properties. 请注意,默认情况下,PowerShell将以列表形式呈现输出,因为您的对象具有4个以上的属性。 Pipe it through Format-List -AutoSize to get tabular output. 通过Format-List -AutoSize进行管道输出以获得表格输出。

To complement Ansgar Wiecher's elegant answer with background information : 背景信息 补充 Ansgar Wiecher的优雅答案

Let's define sample input that simulates a single, nested object converted to a PowerShell [pscustomobject] instance via ConvertFrom-Json : 让我们定义样本输入,模拟通过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'} 
}

Outputting $objFromJson gives output that is formatted as in the question. 输出$objFromJson会给出在问题中格式化的输出。

Why does this result in the output formatting shown in the question? 为什么这会导致问题中显示的输出格式?

For types such as [pscustomobject] , which do not have explicit formatting definitions defined for them (via *.ps1xml files and loaded implicitly into the session or explicitly via Update-FormatData ), PowerShell decides what default formatting to use based on the number of properties of the type: 对于[pscustomobject]等类型,它们没有 为它们定义明确的格式化定义 (通过*.ps1xml文件并隐式加载到会话中或通过Update-FormatData显式加载),PowerShell根据数量确定要使用的默认格式。属性类型:

  • A type with up to 4 properties implicitly uses Format-Table 具有最多4个属性的类型隐式使用Format-Table
  • a type with 5 or more properties implicitly uses Format-List 具有5个或更多属性的类型隐式使用Format-List

The sample input in the question is presumably abridged ; 问题中的样本输入可能是删节的 ; with truly only 4 properties, a tabular display would have resulted. 真正只有4个属性,会产生表格显示。

The properties themselves are rendered by calling .PSObject.ToString() on their values, which is typically the same representation you'd get if you referenced the object inside a double-quoted string, except that the latter always uses culture- invariant formatting, whereas .ToString() will respect the current culture, if the type supports it. 属性本身是通过在其值上调用.PSObject.ToString()来呈现的 ,这通常与您在双引号字符串中引用对象时获得的表示形式相同,除了后者始终使用文化不变格式,而.ToString()将尊重当前的文化,如果类型支持它。

In the case of a [pscustomobject] instance, this results in a representation that resembles a hashtable literal, but isn't one (for background information, see this answer ); [pscustomobject]实例的情况下,这会产生类似于哈希表文字的表示,但不是一个(对于背景信息,请参阅此答案 ); eg: 例如:

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

Reshaping the data as desired: 根据需要重塑数据:

There is no way to use formatting cmdlets such as Format-Table directly to yield the desired output - the data must be reshaped first: 没有办法使用格式化小命令如Format-Table 直接得到所需的输出-数据必须首先重塑

Specifically, the properties of object $objFromJson must be reshaped into a collection of custom objects : 具体来说,对象$objFromJson的属性必须重新整形为自定义对象集合

  • whose Name property contains the name of a given property, and Name属性包含给定属性的名称 ,以及

  • whose other properties are the properties of the object of that property's value ; 它的另一个属性是属性的对象的属性; in other words: the properties of the input property's value must be made properties of the output object itself. 换句话说:输入属性值的属性必须是输出对象本身的属性。

Extracting $objFromJson 's properties is facilitated by PowerShell adding (among others) a hidden .PSObject property to all objects, whose own .Properties property contains a collection of all the object's property definitions (name, value, additional metadata such as the type of property, ...); PowerShell为所有对象添加(以及其他)隐藏的.PSObject属性,便于提取$objFromJson的属性,其自己的.Properties属性包含所有对象的属性定义的集合(名称,值,附加元数据,如类型财产,......); eg: 例如:

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

Outputting the collection of $objFromJson 's property definitions and extracting only the definitions' Name and Value properties is a step in the right direction: 输出$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}

However, we must make the properties of the .Value property direct properties of the output objects to get output with property-individual values. 但是,我们必须使输出对象的.Value属性直接属性的属性获得具有属性 - 个别值的输出。

Ansgar's elegant answer demonstrates how to do that in a single pipeline. Ansgar的优雅答案演示了如何在单一管道中实现这一目标。
Let me complement it with a reusable helper function derived from it: 让我用从它派生的可重用辅助函数来补充它:

function ConvertTo-Collection($InputObject) {
  foreach ($obj in $InputObject) {
    foreach ($prop in $obj.PSObject.Properties) {
      $prop.Value | Select-Object @{ n='Name'; e={ $prop.Name }}, *
    }
  } 
}

With that function in place, the desired output can now be achieved thus: 有了这个功能,现在可以实现所需的输出:

ConvertTo-Collection $objFromJson | Format-Table

To exclude a specific property, such as key3 : 要排除特定属性,例如key3

ConvertTo-Collection $objFromJson | Select-Object -ExcludeProperty key3 |
  Format-Table

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM