问题
It's my first time, so let me know if I'm doing something wrong with the layout of my question.
I have a lot of JSON files with filenames that follow a naming convention, i.e. file1.json, file2.json, etc. Each of which are likely to have multiple objects which look like:
[
{
"Forename": "Jim",
"Surname": "Cook",
"Gender": "M",
"DOB": "12-03-1994"
},
{
"Forename": "Sarah",
"Surname": "Parker",
"Gender": "F",
"DOB": "01-02-1983"
},
{
"Forename": "Alan",
"Surname": "Flemming",
"Gender": "M",
"DOB": "27-10-1989"
}
]
In Powershell, I would like to convert these JSON objects into Powershell objects and then select objects with the same value for a property, like people whose first name is "Jim".
So far I've achieved this:
@(Get-ChildItem "file*.json" | %{Get-Content $_.FullName | Out-String | ConvertFrom-Json}) | Where-Object {$_.Forename -eq "Jim"}
This works when there is only one file to work with, which outputs:
Forename Surname Gender DOB
-------- ------- ------ ---
Jim Cook M 12-03-1994
However it fails and outputs all objects when used with multiple files, as though the Where-Object is being ignored. The result can look like this:
Forename Surname Gender DOB
-------- ------- ------ ---
Jim Cook M 12-03-1994
Sarah Parker F 01-02-1983
Alan Flemming M 27-10-1989
Bill Preston M 04-07-1975
Helen Smith F 03-12-2001
Can someone please suggest what I'm doing wrong here and how it can be fixed to get the correct result? Thanks
回答1:
The problem is that ConvertFrom-Json
outputs (converted-from-)JSON arrays as single objects rather than element by element, as is otherwise typical in PowerShell.
This problematic behavior is the subject of this GitHub issue.
This results in the entire array getting output by Where-Object
if (at least) one of its elements has a .ForeName
property with value Jim
, thanks to member enumeration.
The workaround is to force enumeration, which in the simplest case is achieved by wrapping the command the ConvertFrom-Json
call in (...)
:
Get-ChildItem file*.json | ForEach-Object {
(Get-Content -Raw $_.FullName | ConvertFrom-Json)
} | Where-Object { $_.Forename -eq "Jim" }
Note that I've replaced Get-Content $_.FullName | Out-String
with Get-Content -Raw $_.FullName
(PSv3+), which is both more concise and more efficient for retrieving a file's content as a single, multi-line string.
来源:https://stackoverflow.com/questions/55500059/read-multiple-json-files-into-an-array-of-powershell-objects-and-filter-out-thos