2

我在将哈希表添加到多维数组时遇到问题。我编写了以下代码:

$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”。我检查了“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
    +fullyQualifiedErrorId:PropertyAssignmentException

你知道我如何添加@{Person="Max";Alter="35"}到“Bücher”吗?

4

1 回答 1

1

tl;博士

不支持通过成员枚举设置键/属性值(见下文)。

相反,您必须获取要显式修改其属性的特定对象.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 问题 #5271,尤其是 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.
...
于 2018-03-21T15:16:45.083 回答