我有两个Byte[]类型的变量(我选择此类型是为了满足特定需要,因此需要保留它。),它们声明为:
$first = New-Object Byte[] 32
$second = New-Object Byte[] 32
Run Code Online (Sandbox Code Playgroud)
并且,我初始化了两个变量的每个索引。
现在,我创建了一个哈希表$List1:
$List1=@{"First" = $first; "Second" = $second}
Run Code Online (Sandbox Code Playgroud)
我使用以下语法来创建 json 文件:
$List1 | ConvertTo-Json | Set-Content -Path $jsonFile1
Run Code Online (Sandbox Code Playgroud)
这是第一个json文件内容:
{
"First": {
"value": [
210,
195,
131,
176,
88,
154,
57,
37,
2,
75,
182,
190,
156,
43,
113,
199,
63,
25,
109,
92,
220,
91,
219,
252,
113,
68,
202,
12,
147,
194,
36,
177
],
"Count": 32
},
"Second": {
"value": [
238,
225,
12,
172,
134,
94,
42,
204,
27,
78,
39,
166,
229,
111,
143,
254
],
"Count": 16
}
}
Run Code Online (Sandbox Code Playgroud)
然后我将第一个 json 文件读入临时变量,如下所示:
$tempHash = Get-Content -Path $jsonFile1 -Raw| ConvertFrom-Json
Run Code Online (Sandbox Code Playgroud)
由于$tempHash是 a PSCustomObject,我创建一个新的哈希表$List2,如下所示:
$List2 = @{"First" = $tempHash.First.value; "Second"= $tempHash.Second.value}
Run Code Online (Sandbox Code Playgroud)
我用它来创建第二个 json 文件,如下所示:
$List2 | ConvertTo-Json | Set-Content -Path $jsonFile2
Run Code Online (Sandbox Code Playgroud)
这是第二个json文件内容:
{
"First": [
133,
231,
19,
173,
60,
50,
105,
68,
38,
109,
99,
155,
2,
188,
216,
9,
8,
225,
203,
15,
167,
8,
188,
76,
192,
154,
183,
194,
1,
122,
143,
137
],
"Second": [
27,
3,
57,
67,
155,
145,
181,
194,
250,
10,
65,
90,
41,
230,
243,
196
]
}
Run Code Online (Sandbox Code Playgroud)
我使用相同的语法来创建这两个 json 文件。那么,为什么它们的结构不同呢?
[编辑]
我怀疑,差异是因为这种语法:
$List1=@{"First" = $first; "Second" = $second}
Run Code Online (Sandbox Code Playgroud)
因为Byte[]类型变量不能作为简单integer[]类型变量工作。纠正我。
[编辑]
所以,事实证明Byte[]类型变量有两个不同的键。“value”保存实际的字节值数组,“Count”保存变量中的元素数量Byte[]。但是,当我们像这样调用Byte[]类型变量时:
$first
Run Code Online (Sandbox Code Playgroud)
这是Byte[]类型,我们只获得“value”键下列出的值。“count”键下的值永远不会显示在控制台中,但它会以某种方式传递到哈希表。
并且,还有一点需要注意。如果我使用:
$List2 = @{"First" = $tempHash.First; "Second"= $tempHash.Second}
Run Code Online (Sandbox Code Playgroud)
然后,我将不得不使用:
$List2.First.Value #to get the value of the "First" key
Run Code Online (Sandbox Code Playgroud)
这让我感到不舒服,因为对于$List1哈希表,我只需要使用:
$List1.First #to get the value of the "First" key.
Run Code Online (Sandbox Code Playgroud)
[解决方法]
我创建了一个哈希表$List作为原始哈希表,如下所示,仅供严格使用一次:
$List | ConvertTo-Json | Set-Content -Path $jsonFile
Run Code Online (Sandbox Code Playgroud)
然后,我根据上面的原始创建了两个 hastable $List1,如下所示。$List2$jsonFile
$tempHash = Get-Content -Path $jsonFile -Raw| ConvertFrom-Json
$List1 = @{"First" = $tempHash.First; "Second" = tempHash.Second}
$List2 = @{"First" = $tempHash.First; "Second" = tempHash.Second}
Run Code Online (Sandbox Code Playgroud)
它帮助我在引用它们的键和值时保持一致性。
现在,我用
#to fetch the values of the "First" keys of both hashtables.
$List1.First.value #and
$List2.First.value
Run Code Online (Sandbox Code Playgroud)
同样,我对哈希表$List1和$List2.
#to fetch the values of the "Second" keys of both hashtables.
$List1.Second.value #and
$List2.Second.value
Run Code Online (Sandbox Code Playgroud)
[编辑]
事实证明,这是我的 Powershell 版本中的一个错误,由下面的 @mklement0 测试。完美的解决方案是按照 @mklement0 的指示使用以下语法:
# Ensure that the input array is constructed without the extra [psobject] wrapper.
$First = [Byte[]]::new(32)
$Second = [Byte[]]::new(32)
Run Code Online (Sandbox Code Playgroud)
ConvertTo-Json第一次调用的结果是Windows PowerShell v5.1中的一个怪癖:生成的 JSON 应该直接具有并包含一个数组,而不是一个具有和属性的对象,并且包含该数组。FirstSecondvalueCountvalue
$a = New-Object Byte[] 2; @{ a = $a } | ConvertTo-Json -Compress产量:
{"a":[0,0]}在 PowerShell Core v6.0.1 中 - 好的。{"a":{"value":[0,0],"Count":2}}在 Windows PowerShell v5.1 中 - 损坏。在你的情况下,它的使用触发New-Object了怪癖。
很可能与这个问题有关;但请注意,上述问题在 PowerShell Core 中也没有得到解决,但上面链接的修复解决了这种情况下的问题。
解决方法:
在脚本/会话开始时,运行:
Remove-TypeData System.Array
Run Code Online (Sandbox Code Playgroud)
这将从所有数组对象中删除过时的 ETS 提供的属性,这使得- 包装对象(例如由 所返回).Count的问题消失- 有关说明,请参阅此答案。[psobject]New-Object
比较麻烦的解决方法:
如果您确保-is [psobject]输入数组不再报告 true ,问题就会消失,可以通过以下方式之一完成:
[PSv5+]:$First = [Byte[]]::new(32)- 使用表达式而不是命令可以解决问题,因为它不会创建额外的、不可见的[psobject]包装器。
[PSv4-]:$First = (New-Object Byte[] 32).psobject.BaseObject- 显式绕过额外的[psobject]包装器可以使问题消失。
简化示例(PSv5+,但很容易适应早期版本;省略文件操作,因为它们是问题的附带条件):
# Ensure that the input array is constructed without the extra [psobject] wrapper.
$First = [Byte[]]::new(2)
# Construct a hashtable...
$List1 = @{ First = $first }
# ... and convert it to JSON:
($json = $List1 | ConvertTo-Json)
Run Code Online (Sandbox Code Playgroud)
上面现在可以正确产生(没有value带有和属性的无关对象count):
{
"First": [
0,
0
]
}
Run Code Online (Sandbox Code Playgroud)
现在,将此 JSON 字符串重新转换为对象可以按预期工作:
# Re-convert: $tempObj.First then *directly* contains the input array
# (there is no .Value property anymore).
$tempObj = $json | ConvertFrom-Json
# Construct a new hashtable...
$List2 = @{ First = $tempObj.First }
# ... and convert it to JSON.
$List2 | ConvertTo-Json
Run Code Online (Sandbox Code Playgroud)
结果是与上面相同的 JSON 字符串。