问题描述
我在将哈希表添加到多维数组时遇到问题.我编写了以下代码:
$Data = @{BIBs = @(@{$BIB = @{BIBName=$BIBName},@{Standort = $Standort},@{Bücher = @(@{BuchName = $BuchName;Autor = $Autor})}})}
此代码正在运行并创建一个输出,我将其存储在 JSON 中:
{BIB":[{BIB1":[{"BIBName": "123"},{标准":123"},{Bücher":[{"作者": "123",书名":123"}]}]},{BIB2":[{"BIBname": "345"},{标准":345"},{Bücher":[{"作者": "345",书名":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"添加另一个哈希表.我用
检查了Bücher"的类型$data.BIBs.BIB1.Bücher.GetType()
它实际上是一个数组:
IsPublic IsSerial 名称 BaseType——————————————————真真对象[] 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+ FullQualifiedErrorId:PropertyAssignmentException你知道我是如何将 @{Person="Max";Alter="35"}
添加到Bücher"的吗?
tl;dr
不支持通过成员枚举设置键/属性值(见下文).
相反,您必须获取要显式修改其 .Bücher
属性的特定对象:
($Data.BIBs.BIB1 | ? Bücher).Bücher += @{ BuchName='neues Buch';Autor='约翰·多伊' }
Mathias R. Jessen 在对该问题的评论中提供了关键的指针:
PowerShell 在集合值 属性的点符号方面有意不对称,用于获取 值与设置 值.
在获取时,PSv3+ 应用成员枚举,简而言之,它允许您访问 集合 上的属性,并从 该集合中的每个元素 隐式获取该属性的值,并将结果收集到一个数组.
在设置时,不应用成员枚举;理由是无意修改数据的风险太高 - 请参阅 GitHub 问题 #5271 尤其是 PS 核心成员的此评论团队.
不幸的是当前的错误消息没有告诉你.
它源于这样一个事实:当尝试在集合级别设置一个属性时,该属性仅直接在集合上(而不是在其元素上)被查找,其中它(通常)不存在.
我们来看一个简化的例子:
$data = @{ # 一个哈希表a = ( # 哈希表数组@{ b1 = 'b1' },@{ b2 = 'b2' },@{ b3 =@{ b31 = 'b31' }, @{ b32 = 'b32' } # 哈希表数组})}
在获取后,一切工作正常:
PS>$data.a.b3名称值---- -----b31 b31b32 b32
即使 $data.a
是一个 [object[]]
数组,也找到了一个具有 .b3
属性的对象(哈希表)在它的元素中,输出那个对象的.b3
值.
这是实际中的成员枚举(尽管更典型的用途是属性存在于数组的所有 元素上,以及要在 [object[]] 中收集各个值的情况
数组).
在设置时,PowerShell 放弃成员枚举,因此仅查找.b3
属性失败 直接在 [object[]]
实例上,即 $data.a
,当然,数组没有 .b3
属性:
PS>$data.a.b3 += @{ b33 = 'b33' } # 尝试添加一个元素;!!失败在此对象上找不到属性b3".验证该属性是否存在并且可以设置....
I'm having trouble with adding hashtables to a multidimensional array. I coded the following:
$Data = @{BIBs = @(
@{$BIB = @{BIBName=$BIBName},
@{Standort = $Standort},
@{Bücher = @(
@{BuchName = $BuchName;
Autor = $Autor
})
}}
)}
This code is functioning and creates an output, which I store in a JSON:
{
"BIBs": [
{
"BIB1": [
{
"BIBName": "123"
},
{
"Standort": "123"
},
{
"Bücher": [
{
"Autor": "123",
"BuchName": "123"
}
]
}
]
},
{
"BIB2": [
{
"BIBname": "345"
},
{
"Standort": "345"
},
{
"Bücher": [
{
"Autor": "345",
"Buchname": "345"
}
]
}
]
}
]
}
I have extra code which adds another hashtable to array "BIBs" as you can see.
$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})}
}
When the output is like above, I'm not able to add another hashtable to "Bücher". I checked the type of "Bücher" with
$data.BIBs.BIB1.Bücher.GetType()
and it's actually an array:
IsPublic IsSerial Name BaseType -------- -------- ---- -------- True True Object[] System.Array
I tried
$Data.BIBs.BIB1.Bücher += @{Person="Max";Alter="35"}
to add a new hashtable, like I did with "BIB2", but I am getting the error:
The property 'Bücher' cannot be found on this object. Verify that the property exists and can be set. At line:5 char:1 + $data.BIBs.BIB1.Bücher += @{Motor="asdf";pers="345"} + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : InvalidOperation: (:) [], RuntimeException + FullyQualifiedErrorId : PropertyAssignmentException
Do you know how I add @{Person="Max";Alter="35"}
to "Bücher"?
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' }
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.
...
这篇关于如何将哈希表添加到多维数组?不能通过成员枚举赋值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!