Powershell从多个文件创建对象

Powershell从多个文件创建对象,powershell,pscustomobject,Powershell,Pscustomobject,我正在从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

我正在从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上迭代,根据对象类型,我需要两个不同的代码路径

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

我试图创建一个新对象
$bar
,它包含
$foo
的所有数组项

$bar = new-object psobject
$bar | add-member -name $foo[0].psobject.properties.name -value $foo[0].'derp' -memberType NoteProperty
更新
按照沃尔特·米蒂的要求。如果我加载单个文件并运行
$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
$final=@{}
#循环遍历所有JSON文件,并添加到$Final[]=
ls.\*.json |%{
$o=cat$54;-Raw |从Json转换
$final[$\.name]=[PsCustomObject]$o
}
$final=[PsCustomObject]$final
这将为所有JSON文件生成名称->数据映射,因为嵌套的
PSObject

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

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

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

    • 需要注意的是,如果文件名重复,最后处理的文件将“获胜”

有关Unix样式别名
ls
cat
的用法说明,请参见底部


要获取从JSON对象转换而来的所有对象的数组,以下内容就足够了:

$allObjects = @(Get-ChildItem -Filter *.json | Get-Content -Raw | ConvertFrom-Json)
请注意,如果您只需要一个目录的JSON文件,
$allObjects=@(getcontent-Path*.json-Raw | convertfromjson)
也可以工作

注意使用了数组子表达式操作符
@(…)
,它确保返回的内容被视为数组,即使只返回一个对象也是如此

  • 默认情况下,或者当您使用正则子表达式操作符PowerShell使用
    $(…)
    时,PowerShell将展开任何(可能嵌套的)单个项集合,并仅返回项本身;看

关于PowerShell的
Get ChildItem
Get Content
cmdlet分别使用Unix风格别名
ls
cat
的说明:

  • 由于PowerShell是跨平台的,因此这些别名仅存在于PowerShell的Windows版本中,而已决定在Unix平台上的PowerShell Core中省略它们,以便不影响同名的标准Unix实用程序

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

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

如果两个json文件/对象具有不同值的相同属性,您会期望发生什么?好的一点,如果任何键不唯一,我会期望出现错误。可能是错误的,但我认为对象数组是一个对象。请尝试“$foo[0].gettype”或“$foo[0]| gm”以了解有关$foo中的第一个条目的更多信息。在linux世界中,不鼓励分析
ls
的输出。windows是一样的吗?PowerShell中没有任何东西实际上只返回字符串,它们是带有字段的对象。@spuder ls和cat在PowerShell中主要是
get childitem
get content
@AP的别名。我在您的代码中发现此错误
不能使用飞溅运算符“@”引用表达式中的变量。