Powershell 从多个文件创建对象

Powershell create object from multiple files

我正在从 json 文件制作 PSObject

bar.json

{
  "derp": {
   "buzz": 42 
   },
   "woot":  {
     "toot": 9000
   }
}

我可以使用 ConvertFrom-Json

从 json 中创建一个 PSCustomObject
$foo = Get-Content .\bar.json -Raw |ConvertFrom-Json
$foo.gettype()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     False    PSCustomObject                           System.Object

但是,如果我尝试展开多个 json 文件,我会得到一个数组

$foo = Get-Content .\*.json -Raw |ConvertFrom-Json
$foo.gettype()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     False    Object[]                                 System.Array

为了遍历 $foo,我需要 2 个不同的代码路径,具体取决于对象类型。

我可以从多个 json 文件中获取单个对象吗?
如果没有,我如何将对象数组压缩为单个对象?

我试图创建一个包含 $foo

的所有数组项的新对象 $bar
$bar = new-object psobject
$bar | add-member -name $foo[0].psobject.properties.name -value $foo[0].'derp' -memberType NoteProperty

更新
根据 Walter Mitty 的要求。如果我加载单个文件并且 运行 $foo[0]

$foo = Get-Content .\bar.json -Raw |ConvertFrom-Json
$foo[0].gettype()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     False    PSCustomObject                           System.Object

$foo[0]

derp                                                    woot
------------                                            ------------
@{Provisioners=System.Object[]; OS=windows; Size=; V... @{Provisioners=System.Object[]; OS=windows; Size=; V...

解决方案

我最初实现了 AP 的答案,但后来重构它以使用 mklement0 答案。

虽然 $allObjects 是一个数组,但它仍然允许我按名称引用值,这正是我一直在寻找的

$allObjects = @(
    Get-ChildItem '.\foo' -Filter *.json -Recurse | Get-Content -Raw | ConvertFrom-Json
)

# iterating over nested objects inside an array is hard.
# make it easier by moving all array objects into 1 parent object where 
# the 'key' is the name (opposed to AP's answer where filename = key)
$newObject = New-Object PSObject
foreach ($i in $allObjects) {
    $i.psobject.members | ?{$_.Membertype -eq 'noteproperty'} |%{$newObject | add-member $_.Name $_.Value}
}

如果您想要的只是从不同文件解析的 JSON 个对象的数组:

$final = @{}

# Loop Thru All JSON Files, and add to $Final[<name>] = <JSON>
ls .\*.json | % {
  $o = cat $_ -Raw | ConvertFrom-Json
  $final[$_.name] = [PsCustomObject]$o
}
$final = [PsCustomObject]$final

这将为所有 JSON 文件生成名称 -> 数据映射作为嵌套 PSObject

是创建单个顶级对象([pscustomobject] 实例)的优雅解决方案:

  • 将所有 JSON 转换后的对象作为 以其输入文件名命名的属性 .

    • 例如,$final 将包含一个 bar.json 属性,其值是问题中 JSON 字符串的对象等价物。

    • 需要注意的是,对于重复的文件名,最后处理的文件将 "win".

有关 Unix 风格别名 lscat.

的使用说明,请参阅底部

为了得到一个数组所有转换自-JSON对象,以下就足够了:

$allObjects = @(Get-ChildItem -Filter *.json | Get-Content -Raw | ConvertFrom-Json)

请注意,如果您只需要一个单个目录的JSON个文件,
$allObjects = @(Get-Content -Path *.json -Raw | ConvertFrom-Json) 也有效。

注意 @(...) 的使用,即 array 子表达式运算符,它确保返回的内容被视为 array,即使只返回一个单个对象。

  • 默认情况下,或者当您使用 $(...) 时, 常规 子表达式运算符,PowerShell 解包任何(可能嵌套的)单项集合和 returns只有项目本身;参见 Get-Help about_Operators

有关为 PowerShell 的 Get-ChildItemGet-Content cmdlet 使用 Unix 风格别名 lscat 的说明,分别为:

  • 现在 PowerShell 是跨平台的,这些别名只存在于 Windows 版本的 PowerShell 中,而决定省略它们来自 Unix 平台上的 PowerShell Core,以免影响同名的标准 Unix 实用程序。

  • 最好养成使用 PowerShell 的 自己的 别名 的习惯,这些别名遵循规定的命名约定并且不要与特定于平台的实用程序冲突。

    • 例如,gci 可用于 Get-ChildItem,而 gc 可用于 Get-Content
    • 有关 PowerShell 自身别名背后的命名约定,请参阅 documentation