簡體   English   中英

Powershell為什么兩個json內容之間存在差異?

[英]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

由於$tempHashPSCustomObject ,我創建一個新的哈希表$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應該具有FirstSecond 直接包含數組而不是具有valueCount屬性的對象 ,其value包含數組。

    • PowerShell Core中修復此問題; 它可能會或可能不會在Windows PowerShell中得到修復(從v5.1開始仍然存在)。
      $a = New-Object Byte[] 2; @{ a = $a } | ConvertTo-Json -Compress $a = New-Object Byte[] 2; @{ a = $a } | ConvertTo-Json -Compress產量:
      • PowerShell Core v6.0.1中的{"a":[0,0]} - 好的。
      • {"a":{"value":[0,0],"Count":2}}在Windows PowerShell v5.1中 - BROKEN。
  • 在你的情況下, 使用New-Object觸發怪癖

    • 最有可能的是它與這個問題有關 ; 但請注意,PowerShell Core中的所述問題也未解決,但上面鏈接的修復解決了此上下文中的問題。

解決方法

在腳本/會話開始時,運行:

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)

上面現在正確地產生( 沒有帶有valuecount屬性的無關對象):

{
    "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}

這將保持valuecount結構。 在測試時,它還保持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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM