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