[英]Powershell Core deserializes numbers in JSON as Int64 vs Windows Powershell which does it as Int32
請注意:
Windows PowerShell
C:\> ("1" | ConvertFrom-Json).gettype().name
Int32
C:\>
Powershell 核心
C:\> ("1" | ConvertFrom-Json).gettype().name
Int64
C:\>
這不是良性的。 考慮一個鍵為整數的映射:
$x = @{
123 = 1
}
鍵 123 是Int32
,而不是Int64
。 因此,如果 123 來自解析的 JSON,它將在不同的 shell 中具有不同的類型。 現在:
C:\> $x[[Int32]123]
1
C:\> $x[[Int64]123]
C:\>
這在兩個殼上都是正確的。 這種行為變化破壞了我們使用 REST API 操作事物的自動化腳本。
可以關閉 Powershell Core 的這種行為嗎?
兩個 PowerShell 版本使用不同的實現,導致您觀察到的不同行為:
System.Int64
( [long]
) 的基本原理。 從 PowerShell 7.1 開始,計划通過System.Text.Json
命名空間向現在的本機 .NET JSON 功能(在 .NET Core 3+ 中可用)移動,這可以通過以下方式恢復到System.Int32
( [int]
) 的序列化default ,因為無論如何都不可避免地會發生重大更改:
請參閱GitHub 問題 # 14264 (由iRon基於此問題創建)和GitHub PR #11198 中的討論,該討論正在准備遷移到System.Text.Json
。
一個相關的問題是,太大而無法放入System.Int64
( [long]
) 的數字也以不同的方式序列化(請參閱GitHub 問題 #9207 ):
System.Decimal
( [decimal]
),對於更大的數字System.Double
( [double]
)。System.BigInt
( [bigint]
)。此外,支持的數字格式也存在差異:
的Windows PowerShell不能識別十六進制數(例如, 0x10
),根據JSON規范[1],而PowerShell的[核心]作為V7.1的確實; 然而,作為規范的另一個擴展,兩者都支持科學記數法(例如, 1e2
表示100
)並將其解析為[double]
。
Windows PowerShell中,作為另一個擴展規范,不支持+
-prefixed數字(例如+10
),而PowerShell的[核心]作為V7.1的沒有。
(此外,兩個版本都支持單引號字符串作為擴展名。)
解決方法:
通常,請注意,鑒於 PowerShell 能夠混合不同的數字類型並按需擴展類型,問題通常可能不會浮出水面。
但是,正如問題所示,當數字用作哈希表(字典)的鍵時,必須傳遞類型精確值以進行查找以定位條目。
因此,最簡單的解決方法是將哈希表鍵轉換為[int]
,這允許稍后僅使用[123]
(甚至.123
)進行查找:
# Works in both Windows PowerShell and PowerShell [Core]
# Without the [int] cast, the lookup would fail in PowerShell [Core] as of v7.1
PS> $key = '123' | ConvertFrom-Json; @{ [int] $key = 'bingo' }[123]
bingo
另一種選擇是使用[pscustomobject]
而不是哈希表,在這種情況下,數字鍵隱式成為屬性名稱,屬性名稱始終為字符串。
# Note the use of .123, i.e. property access.
PS> $key = '123' | ConvertFrom-Json; ([pscustomobject] @{ [int] $key = 'bingo' }).123
bingo
這甚至適用於數字變量:
$lookup=123; ([pscustomobject] @{ [int] $key = 'bingo' }).$lookup
警告:當一個鍵被隱式字符串化成為一個屬性名稱時,它總是使用十進制表示; 例如, [pscustomobject] @{ [int] 0x10 = 'bingo' }
會生成一個屬性名稱為'16'
的對象。 [2]
但是,請注意哈希表/字典比[pscustomobject]
更輕量級。
[1] 但是,旨在改進 JSON 的JSON5格式確實支持十六進制。 數字,以及其他顯着改進,例如支持注釋、無關的尾隨逗號和單引號字符串。
[2] 此外,對於[double]
值,轉換是文化敏感的,因此1.2
在某些文化中可能會導致'1.2'
(從 v7.1 開始,這是出乎意料的 - 參見GitHub 問題 #14278 ); 此外,大[double]
可以以科學記數法結束,因此1000000000000000.1
結果為'1E+15'
。 也就是說,考慮到從十進制數轉換的准確性限制,使用[double]
s 作為字典鍵通常是不明智的。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.