Считайте несколько файлов JSON в массив объектов Powershell и отфильтруйте те, которые имеют одинаковое значение для свойства.

Это мой первый раз, поэтому дайте мне знать, если я делаю что-то не так с макетом своего вопроса.

У меня много файлов JSON с именами, соответствующими соглашению об именах, например file1.json, file2.json и т. Д. Каждый из них, вероятно, будет иметь несколько объектов, которые выглядят так:

[
    {
        "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"
    }
]

В Powershell я хотел бы преобразовать эти объекты JSON в объекты Powershell, а затем выбрать объекты с таким же значением для свойства, например людей, чье имя «Джим».

Пока я добился этого:

@(Get-ChildItem "file*.json" | %{Get-Content $_.FullName | Out-String | ConvertFrom-Json}) | Where-Object {$_.Forename -eq "Jim"}

Это работает, когда нужно работать только с одним файлом, который выводит:

Forename Surname Gender DOB
-------- ------- ------ ---
Jim      Cook    M      12-03-1994

Однако он не работает и выводит все объекты при использовании с несколькими файлами, как будто объект Where-Object игнорируется. Результат может выглядеть так:

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

Может кто-нибудь подсказать, что я здесь делаю не так и как это можно исправить, чтобы получить правильный результат? Спасибо


person jhall    schedule 03.04.2019    source источник


Ответы (1)


Проблема в том, что в версиях PowerShell до v6.x ConvertFrom-Json выводит (преобразованные из-) массивы JSON как отдельные объекты, а не элемент за элементом, как это обычно бывает в PowerShell.

  • Примечание. В PowerShell [Core] 7.0 поведение было изменено в соответствии с обычным поведением перечисления элементов и -NoEnumerate переключателем был добавлен в качестве согласия на старое поведение.

В результате весь массив выводится Where-Object, если (по крайней мере) один из его элементов имеет свойство .ForeName со значением Jim, благодаря перечисление членов.

Обходной путь - принудительное перечисление, которое в простейшем случае достигается путем помещения команды в ConvertFrom-Json вызов в (...):

Get-ChildItem file*.json | ForEach-Object {
  (Get-Content -Raw $_.FullName | ConvertFrom-Json)
} | Where-Object { $_.Forename -eq "Jim" }

Обратите внимание, что я заменил Get-Content $_.FullName | Out-String на Get-Content -Raw $_.FullName (PSv3 +), который является более кратким и более эффективным для получения содержимого файла в виде одной многострочной строки.

person mklement0    schedule 03.04.2019