使用Powershell 7.2,在日期、->而不是字符串方面,JSON反序列化为对象的方式似乎发生了变化,现在是日期时间。但我希望有“旧”行为,即它是作为字符串处理的,而不是日期时间。
在Powershell 7.2中使用ConvertFrom时,如何实现所有日期都反序列化为字符串而不是日期时间?
编辑:
$val = '{ "date":"2022-09-30T07:04:23.571+00:00" }' | ConvertFrom-Json
$val.date.GetType().FullName
发布于 2022-11-04 15:14:27
ConvertFrom-Json
不会自动将ISO 8601类时间戳字符串转换为[datetime]
实例这一事实。- Hopefully, the proposal in the GitHub issue he links to, [#13598](https://github.com/PowerShell/PowerShell/issues/13598), will be implemented in the future, which would then simplify the solution to:
尚未实现,截至PowerShell 7.2.x '{“日期”:“2022-09-30T07:04:23.571+00:00”}‘PowerShell从-Json -DateTimeKind无转换
powershell.exe
解决方案有两个缺点:(a)速度慢(必须启动子进程中的单独PowerShell实例),(b)它仅限于Windows。下面的解决方案是您自己的方法的概括,以避免这些问题。这里是generalization of 你自己的过程中的方法
"`0"
) --假设输入本身从未包含这样的字符,这是合理的假设。ConvertFrom-Json
识别时间戳字符串,并且保持不变。[pscustomobject]
输出的ConvertFrom-Json
图进行后处理,以便再次删除注入的NUL字符。- This is achieved with a [`ForEach-Object`](https://learn.microsoft.com/powershell/module/microsoft.powershell.core/foreach-object) call that contains a helper script block that _recursively_ walks the object graph, which has the advantage that it **works with JSON input whose timestamp strings may be** _**at any level of the hierarchy**_ (i.e. they may also be in properties of _nested_ objects).
- **Note**: The assumption is that the timestamp strings are only ever contained as _property values_ in the input; more work would be needed if you wanted to handle input JSON such as `'[ "2022-09-30T07:04:23.571+00:00" ]'` too, where the strings are input objects themselves.
# Sample JSON.
$val = '{ "date":"2022-09-30T07:04:23.571+00:00" }'
$val -replace '"(?=\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}[+-]\d{2}:\d{2}")', "`"`0" | #"
ConvertFrom-Json |
ForEach-Object {
# Helper script block that walks the object graph
$sb = {
foreach ($o in $args[0]) {
if ($o -is [Array]) { # nested array -> recurse
foreach ($el in $o) { & $sb $el } # recurse
}
elseif ($o -is [System.Management.Automation.PSCustomObject]) {
foreach ($prop in $o.psobject.Properties) {
if ($prop.Value -is [Array]) {
foreach ($o in $prop.Value) { & $sb $o } # nested array -> recurse
}
elseif ($prop.Value -is [System.Management.Automation.PSCustomObject]) {
& $sb $prop.Value # nested custom object -> recurse
}
elseif ($prop.Value -is [string] -and $prop.Value -match '^\0') {
$prop.Value = $prop.Value.Substring(1) # Remove the NUL again.
}
}
}
}
}
# Call the helper script block with the input object.
& $sb $_
# Output the modified object.
if ($_ -is [array]) {
# Input object was array as a whole (implies use of -NoEnumerate), output as such.
, $_
} else {
$_
}
}
发布于 2022-11-04 14:31:56
基于@zett42 42的输入,我的解决方案如下:
假设我们知道JSON中使用的日期的regex模式,我将JSON作为字符串,添加一个前缀,这样ConvertFrom-Json
就不会将日期转换为datetime,而是将它保持为string,用ConvertFrom-Json
将它转换为PSCustomObject
,对对象做我需要做的任何事情,用ConvertTo-Json
将它序列化回JSON字符串,然后再次删除前缀。
[string]$json = '{ "date":"2022-09-30T07:04:23.571+00:00", "key1": "value1" }'
[string]$jsonWithDatePrefix = $json -replace '"(\d+-\d+.\d+T\d+:\d+:\d+\.\d+\+\d+:\d+)"', '"#$1"'
[pscustomobject]$jsonWithDatePrefixAsObject = $jsonWithDatePrefix | ConvertFrom-Json
$jsonWithDatePrefixAsObject.key1 = "value2"
[string]$updatedJsonString = $jsonWithDatePrefixAsObject | ConvertTo-Json
[string]$updatedJsonStringWithoutPrefix = $updatedJsonString -replace '"(#)(\d+-\d+.\d+T\d+:\d+:\d+\.\d+\+\d+:\d+)"', '"$2"'
Write-Host $updatedJsonStringWithoutPrefix
发布于 2022-11-07 20:38:04
另外两种更改日期格式的方法:
Get-Node
使用这个类似于Get-Node
递归函数的mklement0:
$Data = ConvertFrom-Json $Json
$Data |Get-Node -Where { $_.Value -is [DateTime] } | ForEach-Object {
$_.Value = GetDate($_.Value) -Format 'yyyy-MM-ddTHH\:mm\:ss.fffzzz' -AsUTC
}
$Data
DIY
或者自己动手构建自己的Json反序列化器:
function ConvertFrom-Json {
[CmdletBinding()][OutputType([Object[]])] param(
[Parameter(ValueFromPipeLine = $True, Mandatory = $True)][String]$InputObject,
[String]$DateFormat = 'yyyy-MM-ddTHH\:mm\:ss.fffffffzzz', # Default: ISO 8601, https://www.newtonsoft.com/json/help/html/datesinjson.htm
[Switch]$AsLocalTime,
[Switch]$AsOrdered
)
function GetObject($JObject) {
switch ($JObject.GetType().Name) {
'JValue' {
switch ($JObject.Type) {
'Boolean' { $JObject.Value }
'Integer' { 0 + $JObject.Value } # https://github.com/PowerShell/PowerShell/issues/14264
'Date' { Get-Date $JObject.Value -Format $DateFormat -AsUTC:(!$AsLocalTime) } # https://github.com/PowerShell/PowerShell/issues/13598
Default { "$($JObject.Value)" }
}
}
'JArray' {
,@( $JObject.ForEach{ GetObject $_ } )
}
'JObject' {
$Properties = [Ordered]@{}
$JObject.ForEach{ $Properties[$_.Name] = GetObject $_.Value }
if ($AsOrdered) { $Properties } else { [PSCustomObject]$Properties } # https://github.com/PowerShell/PowerShell/pull/17405
}
}
}
GetObject ([Newtonsoft.Json.Linq.JObject]::Parse($InputObject))
}
使用:
ConvertFrom-Json $Json -DateFormat 'yyyy-MM-ddTHH\:mm\:ss.fffzzz' |ConvertTo-Json -Depth 9
https://stackoverflow.com/questions/74314557
复制相似问题