Как добавить хеш-таблицу в многомерный массив? Невозможно присвоить значения через перечисление членов

У меня проблемы с добавлением хеш-таблиц в многомерный массив. Я закодировал следующее:

$Data = @{BIBs = @(
    @{$BIB = @{BIBName=$BIBName}, 
    @{Standort = $Standort}, 
    @{Bücher = @(
        @{BuchName = $BuchName; 
        Autor = $Autor
        })
    }}
)}

Этот код работает и создает вывод, который я сохраняю в JSON:

{
    "BIBs": [
        {
            "BIB1": [
                {
                    "BIBName": "123"
                },
                {
                    "Standort": "123"
                },
                {
                    "Bücher": [
                        {
                            "Autor": "123",
                            "BuchName": "123"
                        }
                    ]
                }
            ]
        },
        {
            "BIB2": [
                {
                    "BIBname": "345"
                },
                {
                    "Standort": "345"
                },
                {
                    "Bücher": [
                        {
                            "Autor": "345",
                            "Buchname": "345"
                        }
                    ]
                }
            ]
        }
    ]
}

У меня есть дополнительный код, который добавляет еще одну хеш-таблицу в массив "BIB", как вы можете видеть.

$jsonfile = "C:\Skripte\bibV2-1000.json"
$Data = Get-Content $jsonfile | ConvertFrom-Json
$Data.BIBs += New-Object -TypeName PSObject -Property @{
    $BIB = @{BIBname=$BIBName}, @{Standort=$Standort},
           @{Bücher = @(@{Buchname=$BuchName;Autor=$Autor})}
}

Когда вывод такой, как указано выше, я не могу добавить еще одну хеш-таблицу в "Bücher". Я проверил тип "Бюхер" с

$data.BIBs.BIB1.Bücher.GetType()

и это на самом деле массив:

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

Я старался

$Data.BIBs.BIB1.Bücher += @{Person="Max";Alter="35"}

добавить новую хеш-таблицу, как я сделал с "BIB2", но я получаю ошибку:

Свойство 'Bücher' не может быть найдено на этом объекте. Убедитесь, что свойство
существует и может быть установлен.
В строке:5 символов:1
+ $data.BIBs.BIB1.Bücher += @{Motor="asdf";pers="345"}
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~
    + CategoryInfo: InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId: PropertyAssignmentException

Вы знаете, как я добавляю @{Person="Max";Alter="35"} в "Бюхер"?

1 ответ

ТЛ; др

Установка значения ключа / свойства с помощью перечисления членов не поддерживается (см. Ниже).

Вместо этого вы должны получить конкретный объект, чей .Bücher свойство, которое вы хотите явно изменить:

($Data.BIBs.BIB1 | ? Bücher).Bücher += @{ BuchName='neues Buch'; Autor='Johann Doe' }

Примечание: это предполагает, что:
* только один элемент массива $Data.BIBs.BIB1 имеет .Bücher свойство (ключ)
* что, если свойство / ключ существует, оно непусто и, следовательно, является "правдивым" в булевом контексте, таком как выражение, переданное в ? ( Where-Object ); как перечисление членов, это упрощенное Where-Object синтаксис - ? Bücher вместо ? { $_.Bücher } - это функция PSv3+, называемая оператором сравнения.


Mathias R. Jessen предоставил ключевой указатель в комментариях к вопросу:

PowerShell имеет преднамеренную асимметрию относительно точечной нотации в свойствах с коллекционными значениями для получения значений по сравнению с настройками значений.

  • При получении PSv3+ применяет перечисление членов, которое, в двух словах, позволяет получить доступ к свойству коллекции и неявно получить значение этого свойства из каждого элемента в этой коллекции, а результаты собираются в массиве.

  • При настройке перечисление членов не применяется; обоснование заключается в том, что риск непреднамеренного изменения данных слишком высок - см. эту проблему GitHub и, в частности, этот комментарий одного из основных членов команды PS.

К сожалению, текущее сообщение об ошибке не говорит вам об этом.
Это связано с тем, что при попытке установить свойство на уровне коллекции, свойство ищется только непосредственно в коллекции (а не в ее элементах), где оно (обычно) не существует.

Давайте посмотрим на упрощенный пример:

$data = @{ # a hashtable
  a = ( # array of hashtables
    @{ b1 = 'b1' },
    @{ b2 = 'b2' },
    @{ b3 = 
      @{ b31 = 'b31' }, @{ b32 = 'b32' } # array of hashtables
    }
  )
}

При получении все отлично работает

PS> $data.a.b3

Name                           Value                                                                                                                                                                                                                            
----                           -----                                                                                                                                                                                                                            
b31                            b31                                                                                                                                                                                                                              
b32                            b32                                                                                                                                                                                                                              

Даже если $data.a является [object[]] массив, объект (хеш-таблица) со свойством .b3 был найден среди его элементов, и этот объект .b3 значение выводится.
Это перечисление членов в действии (хотя более типичное использование - это свойство существовать во всех элементах массива и отдельные значения, собираемые в [object[]] массив).

При установке PowerShell отказывается от перечисления членов и, следовательно, безуспешно ищет .b3 собственность только непосредственно на [object[]] экземпляр, который является $data.a и, конечно же, массивы не имеют .b3 имущество:

PS> $data.a.b3 += @{ b33 = 'b33' }  # Try to add an element; !! FAILS

The property 'b3' cannot be found on this object. 
Verify that the property exists and can be set.
...
Другие вопросы по тегам