I\'m having trouble with adding hashtables to a multidimensional array. I coded the following:
$Data = @{BIBs = @(
tl;dr
Setting a key / property value via member enumeration is not supported (see below).
Instead, you must obtain the specific object whose .Bücher
property you want to modify explicitly:
($Data.BIBs.BIB1 | ? Bücher).Bücher += @{ BuchName='neues Buch'; Autor='Johann Doe' }
Note: This assumes that:
$Data.BIBs.BIB1
has a .Bücher
property (key)?
(Where-Object
); like member enumeration, this simplified Where-Object
syntax - ? Bücher
instead of ? { $_.Bücher }
- is a PSv3+ feature called comparison statement.
Mathias R. Jessen has provided the crucial pointer in comments on the question:
PowerShell has an intentional asymmetry with respect to dot notation across collection-valued properties for getting values vs. setting values.
On getting, PSv3+ applies member enumeration, which, in a nutshell, allows you to access a property on a collection and implicitly get that property's value from each element IN that collection, with the results getting collected in an array.
On setting, member enumeration is not applied; the rationale is that the risk of unintentional modification of data is too high - see GitHub issue #5271 and in particular this comment by a core member of the PS team.
The unfortunate aspect is that the current error message doesn't tell you that.
It stems from the fact that when attempting to set a property at the collection level, the property is looked for only directly on the collection (instead of on its elements), where it (usually) doesn't exist.
Let's take a look at a simplified example:
$data = @{ # a hashtable
a = ( # array of hashtables
@{ b1 = 'b1' },
@{ b2 = 'b2' },
@{ b3 =
@{ b31 = 'b31' }, @{ b32 = 'b32' } # array of hashtables
}
)
}
On getting, everything works fine:
PS> $data.a.b3
Name Value
---- -----
b31 b31
b32 b32
Even though $data.a
is an [object[]]
array, an object (hashtable) with property .b3
was found among its elements, and that object's .b3
value is output.
This is member enumeration in action (although the more typical uses is case for the property to exist on all elements of the array and for the individual values to be collected in an [object[]]
array).
On setting, PowerShell forgoes member enumeration and therefore unsuccessfully looks for a .b3
property only directly on the [object[]]
instance that is $data.a
and, of course, arrays have no .b3
property:
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.
...