Powershell create object from multiple files

僤鯓⒐⒋嵵緔 提交于 2019-12-11 00:50:01

问题


I am making a PSObject from a json file

bar.json

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

I can make a PSCustomObject form the json using ConvertFrom-Json

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

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

However if I try and splat multiple json files, I get an array

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

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

In order to iterate over $foo, I need 2 different code paths depending on the object type.

Can I get a single object from multiple json files?
If not, how would I compress an array of objects into a single object?

I've tried to make a new object $bar that contains all the array items of $foo

$bar = new-object psobject
$bar | add-member -name $foo[0].psobject.properties.name -value $foo[0].'derp' -memberType NoteProperty

Update
Per Walter Mitty's request. If I load a single file and run $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...

Solution

I initially implemented AP's answer, but later refactored it to use mklement0 answer.

While $allObjects is an array, it still allows me to reference values by name which is what I was looking for

$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}
}

回答1:


If all you want is an Array of JSON objects which are parsed from the different files:

$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

This will produce a Name -> Data map for all your JSON files as a nested PSObject




回答2:


AP.'s helpful answer is an elegant solution for creating a single top-level object ([pscustomobject] instance) that:

  • houses all JSON-converted objects as properties named for their input filenames.

    • E.g., $final would contain a bar.json property whose value is the object equivalent of the JSON string from the question.

    • A caveat is that with duplicate filenames the last file processed would "win".

See bottom for a usage note re Unix-style aliases ls and cat.


To get an array of all converted-from-JSON objects, the following is sufficient:

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

Note that if you only need a single directory's JSON files,
$allObjects = @(Get-Content -Path *.json -Raw | ConvertFrom-Json) works too.

Note the use of @(...), the array subexpression operator, which ensures that what is returned is treated as an array, even if only a single object is returned.

  • By default, or when you use $(...), the regular subexpression operator, PowerShell unwraps any (potentially nested) single-item collection and returns only the item itself; see Get-Help about_Operators.

A note on the use of Unix-style aliases ls and cat for PowerShell's Get-ChildItem and Get-Content cmdlets, respectively:

  • Now that PowerShell is cross-platform, these aliases only exist in the Windows edition of PowerShell, whereas a decision was made to omit them from PowerShell Core on Unix platforms, so as not to shadow the standard Unix utilities of the same name.

  • It is better to get into the habit of using PowerShell's own aliases, which follow prescribed naming conventions and do not conflict with platform-specific utilities.

    • E.g., gci can be used for Get-ChildItem, and gc for Get-Content
    • For the naming conventions behind PowerShell's own aliases, see the documentation.


来源:https://stackoverflow.com/questions/41066388/powershell-create-object-from-multiple-files

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!