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

Posted

技术标签:

【中文标题】格式化 Invoke-RestMethod 或 ConvertFrom-Json 返回的 [pscustomobject] 实例【英文标题】:Format [pscustomobject] instances returned by Invoke-RestMethod or ConvertFrom-Json 【发布时间】:2017-04-26 15:04:38 【问题描述】:

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

当我打印 json 对象的属性时,我得到如下输出:

PS> 写输出 JSON.Object

对象1:@key1=property; key2=属性; key3=属性; key4=属性
对象2:@key1=property; key2=属性; key3=属性; key4=属性
对象 3:@key1=property; key2=属性; key3=属性; key4=属性
对象4:@key1=property; key2=属性; key3=属性; key4=property

我想看到的输出是这样的:

名称 key1 key2 key3 key4
----- ---- ---- ---- ----
Object1 属性 属性 属性
Object2 属性 属性 属性 属性
Object3 属性 属性 属性 

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

例子:

名称 key1 key2 key4 # ← 不显示 key3
----- ---- ---- ----
Object1 属性 属性 属性
Object2 属性 属性 属性
Object3 属性属性属性

【问题讨论】:

尝试将输出传送到| Format-Table,看看输出是否适合您。 您好,感谢您的回复@MartinBrandl。正如您所建议的,我通过管道传输了 JSON 对象。 Json.object | Format-Table 但是,我的输出仍然显示例如哈希表中的键值。 Object1 位于 @key1=property; key2=property 我已经能够使用嵌套的每个属性来提取这些属性,但除此之外,我不完全确定如何将这些值与相应的对象一起放置。 注意:问题中的输出 resembles 哈希表文字,但那是偶然:见***.com/a/40253364/45375 【参考方案1】:

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

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

请注意,PowerShell 将默认以列表形式呈现输出,因为您的对象具有 4 个以上的属性。通过Format-List -AutoSize 传递它以获取表格输出。

【讨论】:

您好,这是一个卓越的回应。我们很亲!但是,有没有办法让“名称”只在列顶部出现一次,而不是为每个新对象重复? @Badlarry 我不关注。请使用实际和所需的输出更新您的问题。 对不起,我已经用适当的字段更新了我的问题。 就像我在回答中已经说过的那样,通过Format-Table 管道循环输出应该可以满足您的需求。使用Select-Object 上的-Exclude 参数删除特定属性。 @AnsgarWiechers Ansgar 编写的代码运行良好,我也能够重新调整用途并对其进行修改,并且非常理解。感谢我能够用相同的逻辑编写更多的函数。【参考方案2】:

补充 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 的属性必须重新整形为一个自定义对象的集合

Name 属性包含给定属性的名称,并且

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

通过 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属性定义的集合 并仅提取定义的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

【讨论】:

这是一个很好的答案。

以上是关于格式化 Invoke-RestMethod 或 ConvertFrom-Json 返回的 [pscustomobject] 实例的主要内容,如果未能解决你的问题,请参考以下文章

PowerShell 的 Invoke-RestMethod 等效于 curl -u(基本身份验证)

Invoke-RestMethod:发送到标头时找不到请求的身份验证数据

无法使用 Invoke-RestMethod 更新工作项历史记录

用于排队构建的Invoke-RestMethod的Body需要包含什么? [重复]

Powershell Invoke-Restmethod不能将生成的Authtoken用作变量

powershell 使用REST-API的PowerShell V3 Multipart / formdata示例(Invoke-RestMethod)