Powershell为什么两个json内容之间有区别? [英] Powershell Why the difference between the two json contents?
问题描述
我有两个Byte[]
类型的变量(我为特定需要选择了此类型,因此需要保留.),它们声明为:
I have two variables of Byte[]
type (I chose this type for a specific need, so it need to be retained.) which are declared as:
$first = New-Object Byte[] 32
$second = New-Object Byte[] 32
然后,我初始化了两个变量的每个索引.
and, I initalized each index of both the variables.
现在,我创建了一个哈希表$List1
:
Now, I created a hashtable $List1
as:
$List1=@{"First" = $first; "Second" = $second}
我正在使用以下语法创建json文件:
I am using the syntax below for creating the json file:
$List1 | ConvertTo-Json | Set-Content -Path $jsonFile1
这是第一个json文件内容:
This is the first json file content:
{
"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文件读入一个临时变量,如下所示:
Then I read the first json file into a temporary variable as below:
$tempHash = Get-Content -Path $jsonFile1 -Raw| ConvertFrom-Json
由于$tempHash
是PSCustomObject
,因此我将创建一个新的哈希表$List2
,如下所示:
Since $tempHash
is a PSCustomObject
, I create a new hashtable $List2
as below:
$List2 = @{"First" = $tempHash.First.value; "Second"= $tempHash.Second.value}
我用来创建第二个json文件,如下所示:
which I use to create the second json file as below:
$List2 | ConvertTo-Json | Set-Content -Path $jsonFile2
这是第二个json文件内容:
This is the second json file content:
{
"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文件.那么,为什么它们的结构不同?
I am using the same syntax to create both the json files. So, why are their structures different?
我怀疑,区别在于这种语法:
I suspect, the difference is because of this very syntax:
$List1=@{"First" = $first; "Second" = $second}
因为Byte[]
类型变量不能用作简单的integer[]
类型变量.
纠正我.
because Byte[]
type variable does not work as a simple integer[]
type variable.
Correct me.
因此,事实证明Byte[]
类型变量具有两个不同的键.
值"保存字节值的实际数组,以及
计数"保存Byte[]
变量中的元素数.
但是,当我们调用Byte[]
类型的变量时,例如:
So, it turns out Byte[]
type variable has two different keys.
"value" which holds the actual array of byte values, and
"Count" which holds the number of elements in the Byte[]
variable.
However, when we invoke the Byte[]
type variable like:
$first
是Byte[]
类型,我们仅获得值"键下列出的值. "count"键下的值永远不会在控制台中显示,但会以某种方式传递给哈希表.
which is of Byte[]
type, we get only the values listed under the "value" key. The value under the "count" key is never displayed in console, yet it is passed to the hashtable somehow.
还有一点要注意.如果我使用:
And, One more point to be noted. If I use:
$List2 = @{"First" = $tempHash.First; "Second"= $tempHash.Second}
然后,我将不得不使用:
then, I'll have to use:
$List2.First.Value #to get the value of the "First" key
这让我感到不舒服,因为对于$List1
哈希表,我只需要使用:
and that makes me feel uncomfortable because for the $List1
hashtable, I only needed to use:
$List1.First #to get the value of the "First" key.
[解决方法]
我创建了一个hastable $List
作为原始哈希表,如下所示,严格仅 一次使用 :
I created a hastable $List
as the original hashtable as below for strictly one time use only:
$List | ConvertTo-Json | Set-Content -Path $jsonFile
然后,我从上面的原始$jsonFile
如下创建了两个hastables $List1
和$List2
.
Then, I created two hastables $List1
and $List2
as below from the original $jsonFile
above.
$tempHash = Get-Content -Path $jsonFile -Raw| ConvertFrom-Json
$List1 = @{"First" = $tempHash.First; "Second" = tempHash.Second}
$List2 = @{"First" = $tempHash.First; "Second" = tempHash.Second}
当我参考它们的键和值时,这有助于我保持一致.
It helped me keep consistency while referring to their keys and values.
现在,我使用
#to fetch the values of the "First" keys of both hashtables.
$List1.First.value #and
$List2.First.value
类似地,我对哈希表$List1
和$List2
的第二"键也执行相同的操作.
Similarly, I do the same for "Second" key for both hashtables $List1
and $List2
.
#to fetch the values of the "Second" keys of both hashtables.
$List1.Second.value #and
$List2.Second.value
事实证明,这是我的Powershell版本中的错误,如下面的@ mklement0所示. 完美的解决方案是改为使用@ mklement0指示的以下语法:
It turned out to be a bug in my version of Powershell as ststed by @mklement0 below. The perfect solution will be to instead use the syntax below as instructed by @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
属性的 object ,而value
包含该数组.The result of the first
ConvertTo-Json
call is a quirk in Windows PowerShell as of v5.1: the resulting JSON should haveFirst
andSecond
contain an array directly rather than an object withvalue
andCount
properties, withvalue
containing the array.- 此行为已在PowerShell Core 中已修复;在 Windows PowerShell(从v5.1开始仍然存在)中,它可能会修复,也可能不会修复.
$a = New-Object Byte[] 2; @{ a = $a } | ConvertTo-Json -Compress
产量:-
PowerShell Core v6.0.1中的
-
{"a":[0,0]}
-确定.
Windows PowerShell v5.1中的 -
{"a":{"value":[0,0],"Count":2}}
-损坏.
- This behavior has been fixed in PowerShell Core; it may or may not get fixed in Windows PowerShell (still present as of v5.1).
$a = New-Object Byte[] 2; @{ a = $a } | ConvertTo-Json -Compress
yields:{"a":[0,0]}
in PowerShell Core v6.0.1 - OK.{"a":{"value":[0,0],"Count":2}}
in Windows PowerShell v5.1 - BROKEN.
对于您而言,使用
New-Object
会触发该怪癖.- 最有可能与此问题有关;请注意,但是,在PowerShell Core中也无法解决上述问题,但是上面链接的修复程序可以解决这种情况下的问题.
- Most likely it is related to this issue; note, however, that said issue isn't resolved in PowerShell Core either, but the fix linked to above resolves the problems in this context.
解决方法:
在脚本/会话开始时,运行:
At the start of your script/session, run:
Remove-TypeData System.Array
这将从所有数组对象中删除由ETS提供的过时的
.Count
属性,这使[psobject]
包裹的对象(如New-Object
返回的)的问题消失了-有关说明,请参见我的答案.This removes the obsolete ETS-supplied
.Count
property from all array objects, which makes the problem go away for[psobject]
-wrapped objects (such as returned byNew-Object
) - for an explanation, see this answer of mine.更多繁琐的解决方法:
如果您确保
-is [psobject]
不再对输入数组报告为真,问题就消失了,这可以通过以下方式之一完成:The problem goes away if you ensure that
-is [psobject]
no longer reports true for the input arrays, which can be done in one of the following ways:-
[PSv5 +]:
$First = [Byte[]]::new(32)
-使用表达式而不是命令可以使问题消失,因为它不会创建额外的,不可见的[psobject]
包装器.
[PSv5+]:
$First = [Byte[]]::new(32)
- use of an expression rather than a command makes the problem go away, because it doesn't create an extra, invisible[psobject]
wrapper.
[PSv4-]:
$First = (New-Object Byte[] 32).psobject.BaseObject
-显式绕过多余的[psobject]
包装器可以解决问题.[PSv4-]:
$First = (New-Object Byte[] 32).psobject.BaseObject
- explicitly bypassing the extra[psobject]
wrapper makes the problem go away.简化的示例(PSv5 +,但很容易适应较早的版本;省略了文件操作,因为它们是问题的附带内容)
Simplified example (PSv5+, but easily adapted to earlier versions; file operations omitted, because they are incidental to the problem):
# 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
属性的 no 无关对象):The above now correctly yields (no extraneous object with
value
andcount
properties):{ "First": [ 0, 0 ] }
现在可以将此JSON字符串转换为对象了:
Reconverting this JSON string to an object now works as expected:
# 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字符串.
The result is the same JSON string as above.
这篇关于Powershell为什么两个json内容之间有区别?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
-
- 此行为已在PowerShell Core 中已修复;在 Windows PowerShell(从v5.1开始仍然存在)中,它可能会修复,也可能不会修复.