【问题标题】:Powershell create object from multiple filesPowershell 从多个文件创建对象
【发布时间】:2016-12-09 18:08:06
【问题描述】:

我正在从 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 文件中获取单个对象吗?
如果没有,我将如何将一组对象压缩成一个对象?

我尝试创建一个新对象$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 文件/对象具有相同的属性但值不同,您会发生什么?
  • 好点,如果任何键不是唯一的,我预计会出错
  • 我可能错了,但我认为对象数组就是一个对象。
  • 尝试 "$foo[0].gettype" 或 "$foo[0] | gm" 以了解有关 $foo 中第一个条目的更多信息。

标签: powershell pscustomobject


【解决方案1】:

如果你想要的只是一个从不同文件中解析出来的 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

【讨论】:

  • 在 linux 世界中,不鼓励解析 ls 的输出。窗户是一样的吗?
  • PowerShell 中没有任何东西实际上只是返回字符串,它们是带有字段的对象..
  • @spuder ls 和 powershell 中的 cat 仅是 get-childitemget-content @AP 的别名。我的代码出现此错误The splatting operator '@' cannot be used to reference variables in an expression.
【解决方案2】:

AP.'s helpful answer 是一个优雅的解决方案,用于创建单个顶级对象([pscustomobject] 实例):

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

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

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

有关 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 会解开任何(可能嵌套的)单项集合并仅返回项本身;见Get-Help about_Operators

关于将 Unix 样式别名 lscat 分别用于 PowerShell 的 Get-ChildItemGet-Content cmdlet 的说明:

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

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

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

【讨论】:

    猜你喜欢
    • 2016-05-25
    • 2016-01-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-19
    • 2020-06-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多