[英]Powershell Why the difference between the two json contents?
我有两个Byte[]
类型的变量(我为特定需要选择了这个类型,所以需要保留它。)声明为:
$first = New-Object Byte[] 32
$second = New-Object Byte[] 32
并且,我将两个变量的每个索引都初始化了。
现在,我创建了一个哈希表$List1
:
$List1=@{"First" = $first; "Second" = $second}
我使用下面的语法来创建json文件:
$List1 | ConvertTo-Json | Set-Content -Path $jsonFile1
这是第一个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
}
}
然后我将第一个json文件读入临时变量,如下所示:
$tempHash = Get-Content -Path $jsonFile1 -Raw| ConvertFrom-Json
由于$tempHash
是PSCustomObject
,我创建一个新的哈希表$List2
,如下所示:
$List2 = @{"First" = $tempHash.First.value; "Second"= $tempHash.Second.value}
我用它来创建第二个json文件,如下所示:
$List2 | ConvertTo-Json | Set-Content -Path $jsonFile2
这是第二个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
]
}
我使用相同的语法来创建两个json文件。 那么,为什么他们的结构不同?
[编辑]
我怀疑,区别在于这个语法:
$List1=@{"First" = $first; "Second" = $second}
因为Byte[]
类型变量不能作为简单的integer[]
类型变量。 纠正我。
[编辑]
因此,事实证明Byte[]
类型变量有两个不同的键。 “value”保存字节值的实际数组,“Count”保存Byte[]
变量中的元素数。 但是,当我们调用Byte[]
类型变量时,如:
$first
这是Byte[]
类型,我们只获得“value”键下列出的值。 “count”键下的值永远不会显示在控制台中,但它会以某种方式传递给哈希表。
而且,还有一点需要注意。 如果我使用:
$List2 = @{"First" = $tempHash.First; "Second"= $tempHash.Second}
然后,我将不得不使用:
$List2.First.Value #to get the value of the "First" key
这让我觉得不舒服,因为对于$List1
哈希表,我只需要使用:
$List1.First #to get the value of the "First" key.
[解决方法]
我创建了一个hastable $List
作为原始哈希表,如下所示, 仅限一次使用 :
$List | ConvertTo-Json | Set-Content -Path $jsonFile
然后,我从上面的原始$jsonFile
创建了两个hastables $List1
和$List2
,如下所示。
$tempHash = Get-Content -Path $jsonFile -Raw| ConvertFrom-Json
$List1 = @{"First" = $tempHash.First; "Second" = tempHash.Second}
$List2 = @{"First" = $tempHash.First; "Second" = tempHash.Second}
它帮助我在提及键和值时保持一致性。
现在,我用
#to fetch the values of the "First" keys of both hashtables.
$List1.First.value #and
$List2.First.value
类似地,我为hashtables $List1
和$List2
“Second”键执行相同操作。
#to fetch the values of the "Second" keys of both hashtables.
$List1.Second.value #and
$List2.Second.value
[编辑]
事实证明这是我的Powershell版本中的一个错误,如下面的@ mklement0所示。 完美的解决方案是使用@ mklement0指示的下面的语法:
# Ensure that the input array is constructed without the extra [psobject] wrapper.
$First = [Byte[]]::new(32)
$Second = [Byte[]]::new(32)
从v5.1开始,第一个ConvertTo-Json
调用的结果是Windows PowerShell中的一个怪癖 :生成的JSON应该具有First
和Second
直接包含数组,而不是具有value
和Count
属性的对象 ,其value
包含数组。
$a = New-Object Byte[] 2; @{ a = $a } | ConvertTo-Json -Compress
$a = New-Object Byte[] 2; @{ a = $a } | ConvertTo-Json -Compress
产量:
{"a":[0,0]}
- 好的。 {"a":{"value":[0,0],"Count":2}}
在Windows PowerShell v5.1中 - BROKEN。 在你的情况下, 使用New-Object
会触发怪癖 。
解决方法 :
在脚本/会话开始时,运行:
Remove-TypeData System.Array
这将从所有数组对象中删除过时的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)
上面现在正确地产生( 没有带有value
和count
属性的无关对象):
{
"First": [
0,
0
]
}
现在可以按预期方式将此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
结果与上面的JSON字符串相同。
改变这个:
$List2 = @{"First" = $tempHash.First.value; "Second"= $tempHash.Second.value}
对此:
$List2 = @{"First" = $tempHash.First; "Second"= $tempHash.Second}
这将保持value
和count
结构。 在测试时,它还保持value
部分中值的顺序。
编辑
要增强您的解决方法,您可以执行此步骤,以便无需使用.value
即可访问这些值:
$firstValues = [byte[]]($tempHash.First.value)
$secondValues = [byte[]]($tempHash.Second.value)
$List1 = @{"First" = $firstValues; "Second" = $secondValues}
$List2 = @{"First" = $firstValues; "Second" = $secondValues}
自包含的测试脚本
$jsonFile1 = "jsonFile1.json"
$jsonFile2 = "jsonFile2.json"
$first = New-Object Byte[] 32
$second = New-Object Byte[] 16
foreach($i in 0..($first.COunt -1)){
$first[$i] = Get-random -minimum 1 -maximum 254
}
foreach($i in 0..($second.COunt -1)){
$second[$i] = Get-random -minimum 1 -maximum 254
}
$List = @{"First" = $first; "Second" = $second}
$List | ConvertTo-Json | Set-Content -Path $jsonFile1
$tempHash = Get-Content -Path $jsonFile1 -Raw | ConvertFrom-Json
$firstValues = [byte[]]($tempHash.First.value)
$secondValues = [byte[]]($tempHash.Second.value)
$List1 = @{"First" = $firstValues; "Second" = $secondValues}
$List2 = @{"First" = $firstValues; "Second" = $secondValues}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.