Powershell为什么这两个json内容之间存在差异?

Powershell为什么这两个json内容之间存在差异?,json,powershell,Json,Powershell,我有两个Byte[]类型的变量(我选择这种类型是为了满足特定的需要,所以需要保留),它们声明为: $first = New-Object Byte[] 32 $second = New-Object Byte[] 32 我初始化了这两个变量的每个指数 现在,我创建了一个hashtable$List1,如下所示: $List1=@{"First" = $first; "Second" = $second} 我使用以下语法创建json文件: $List1 | ConvertTo-Json | S

我有两个
Byte[]
类型的变量(我选择这种类型是为了满足特定的需要,所以需要保留),它们声明为:

$first = New-Object Byte[] 32
$second = New-Object Byte[] 32
我初始化了这两个变量的每个指数

现在,我创建了一个hashtable
$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
       }
}
    {
"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文件读入一个临时变量,如下所示:

$tempHash = Get-Content -Path $jsonFile1 -Raw| ConvertFrom-Json
$List2 = @{"First" = $tempHash.First.value; "Second"= $tempHash.Second.value}
$List2 | ConvertTo-Json | Set-Content  -Path $jsonFile2
由于
$tempHash
是一个
PSCustomObject
,我创建了一个新的哈希表
$List2
,如下所示:

$tempHash = Get-Content -Path $jsonFile1 -Raw| ConvertFrom-Json
$List2 = @{"First" = $tempHash.First.value; "Second"= $tempHash.Second.value}
$List2 | ConvertTo-Json | Set-Content  -Path $jsonFile2
我使用它创建第二个json文件,如下所示:

$tempHash = Get-Content -Path $jsonFile1 -Raw| ConvertFrom-Json
$List2 = @{"First" = $tempHash.First.value; "Second"= $tempHash.Second.value}
$List2 | ConvertTo-Json | Set-Content  -Path $jsonFile2
这是第二个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
       }
}
    {
"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[]
type变量有两个不同的键。 保存字节值的实际数组的“value”,以及 “Count”,它保存
字节[]
变量中的元素数。 但是,当我们调用
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
作为原始hashtable,如下所示,仅供一次使用:

然后,我从上面的原始
$jsonFile
创建了两个hastable
$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
类似地,我对哈希表
$List1
$List2
的“Second”键执行相同的操作

#to fetch the values of the "Second" keys of both hashtables.
$List1.Second.value #and
$List2.Second.value
[编辑]

它原来是我的Powershell版本中的一个bug,由下面的@mklement0测试。 完美的解决方案是按照@mklement0的指示使用以下语法:

# Ensure that the input array is constructed without the extra [psobject] wrapper.
$First = [Byte[]]::new(32)
$Second = [Byte[]]::new(32)
更改此项:

$List2 = @{"First" = $tempHash.First.value; "Second"= $tempHash.Second.value}
为此:

$List2 = @{"First" = $tempHash.First; "Second"= $tempHash.Second}
这将维护
计数
结构。在测试时,它还保持了
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}
  • 从v5.1开始,第一个
    ConvertTo Json
    调用的结果是Windows PowerShell中的一个怪癖:生成的Json应该具有
    first
    Second
    直接包含数组,而不是具有
    value
    Count
    属性的对象,包含数组的

    • 这种行为已经被证实;它可能会在Windows PowerShell中得到修复,也可能不会得到修复(从v5.1起仍然存在)。
      $a=新对象字节[]2@{a=$a}|转换为Json-压缩
      产生:
      • PowerShell Core v6.0.1中的
        {“a”:[0,0]}
        -正常
      • Windows PowerShell v5.1中的{“a”:{“value”:[0,0],“Count”:2}已损坏
  • 在你的例子中,正是使用
    新对象
    触发了这个怪癖

    • 最有可能的原因是:;但是,请注意,上述问题在PowerShell Core中也没有得到解决,但上面链接的修复程序解决了此上下文中的问题

解决方法

在脚本/会话开始时,运行:

Remove-TypeData System.Array
这将从所有数组对象中删除过时的ETS提供的
.Count
属性,这使得
[psobject]
-包装对象(如
新对象返回的对象)的问题消失-有关说明,请参阅我的


更麻烦的解决方法

如果确保输入数组的
-is[psobject]
不再报告true,则问题就会消失,这可以通过以下方法之一完成:

  • [PSv5+]:
    $First=[Byte[]]::new(32)
    -使用表达式而不是命令可以解决问题,因为它不会创建额外的、不可见的
    [psobject]
    包装器

  • [PSv4-]:
    $First=(新对象字节[]32).psobject.BaseObject
    -显式绕过额外的
    [psobject]
    包装可以解决问题

简化示例(PSv5+,但很容易适应早期版本;省略了文件操作,因为它们是问题的附带原因):

以上结果现在正确地产生(没有具有
计数
属性的无关对象):

将此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字符串。

。即使在将
$temphash
中的值强制转换为
[byte[]]
时,json输出也是不同的。步骤中似乎发生了一些可疑的事情,这解决了问题。然而,当我们调用Byte[]类型的变量时,比如:$first,它是Byte[]类型的,我们只得到“value”键下列出的值。“count”键下的值永远不会显示在控制台中,但它会以某种方式传递到哈希表中。还要注意的一点是:如果我使用$List2=@{“First”=$tempHash.First;“Second”=$tempHash.Second}现在,我必须使用$List2.First.value到g