Read multiple JSON files into an array of Powershell objects and filter out those with the same value for a property

扶醉桌前 提交于 2019-12-23 04:12:11

问题


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

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