问题
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 abar.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 forGet-ChildItem
, andgc
forGet-Content
- For the naming conventions behind PowerShell's own aliases, see the documentation.
- E.g.,
来源:https://stackoverflow.com/questions/41066388/powershell-create-object-from-multiple-files