在对Invoke-Restmethod的响应进行反序列化后,禁用到UTC时区的转换 [英] Disable conversion to UTC timezone after deserialization of a response from Invoke-Restmethod
问题描述
我使用Invoke-RestMethod从REST API获取数据。响应的属性之一是日期。当使用邮递员或其他工具获取数据时,日期返回正确,但当我使用PowerShell(5.1.19041.906版)及其Invoke-RestMethod时,如下所示:
$response = Invoke-RestMethod -Method Get -Uri $url -Headers $requestHeaders
Date属性中的所有值都会自动转换为UTC。有什么办法可以停用这个变速箱吗?我需要API返回的原始值。
推荐答案
Invoke-RestMethod
,当获得JSON响应时,它会自动将其解析为[pscustomobject]
图;从某种意义上说,它具有ConvertFrom-Json
内置。
当ConvertFrom-Json
确实识别输入JSON中日期的字符串表示形式时,它会将它们转换为[datetime]
实例。
在Windows PowerShell(V5.1,最新也是最终版本)和PowerShell(Core)7.2中,您无法控制类实例的构造,这反映在.Kind
property:
在Windows PowerShell中,需要自定义日期字符串格式(例如
"/Date(1633984531266)/"
),您总是获取Utc
个实例。- 在PowerShell(Core)7+中,额外识别是ISO 8601日期-时间字符串的(变体)的字符串值(例如
"2021-10-11T13:27:12.3318432-04:00"
),.Kind
值取决于字符串值的细节:- 如果字符串以
Z
结尾,表示UTC,则您将获得Utc
实例。 - 如果字符串以UTC偏移量结尾,例如
-04:00
,则得到Local
实例(即使偏移量为00:00
) - 否则将获得
Unspecified
实例。
- 如果字符串以
虽然Windows PowerShell将不会看到新功能,但PowerShell(Core):GitHub issue #13598建议在ConvertFrom-Json
中添加-DateTimeKind
参数,以允许显式请求感兴趣的类型,并交替构造[datetimeoffset]
实例,这是更可取的。
解决办法:
- 注意:如果您需要完全按照定义访问原始字符串值,下面的解决方案将不起作用。您必须检索原始JSON文本并执行您自己的解析,使用
Invoke-WebRequest
和响应的.Content
属性,如Mathias R. Jessen所示。
以下代码片段遍历[pscustomobject]
图,从Invoke-RestMethod
返回,并显式将遇到的任何[datetime]
实例转换为Local
实例就地(Unspecified
实例被视为Local
):
# Call Invoke-RestMethod to retrieve and parse a web service's JSON response.
$fromJson = Invoke-RestMethod ...
# Convert any [datetime] instances in the object graph that aren't already
# local dates (whose .Kind value isn't already 'Local') to local ones.
& {
# Helper script block that walks the object graph.
$sb = {
foreach ($el in $args[0]) { # iterate over elements (if an array)
foreach ($prop in $el.psobject.Properties) {
# iterate over properties
if ($dt = $prop.Value -as [datetime]) {
switch ($dt.Kind) {
'Utc' { $prop.Value = $dt.ToLocalTime() }
# Note: calling .ToLocalTime() is not an option, because it interprets
# an 'Unspecified' [datetime] as UTC.
'Unspecified' { $prop.Value = [datetime]::new($dt.Ticks, 'Local') }
}
}
elseif ($prop.Value -is [Array] -or $prop.Value -is [System.Management.Automation.PSCustomObject]) {
& $sb $prop.Value # recurse
}
}
}
}
# Start walking.
& $sb $args[0]
} $fromJson
# Output the transformed-in-place object graph
# that now contains only Local [datetime] instances.
$fromJson
这篇关于在对Invoke-Restmethod的响应进行反序列化后,禁用到UTC时区的转换的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!