使用 Powershell 7.2,JSON 如何根據日期反序列化為物件的方式似乎發生了變化-> 現在是日期時間而不是字串。但我想要“舊”行為,即它被處理為字串而不是日期時間。
在 Powershell 7.2 中使用 ConvertFrom-Json 時,如何將所有日期反序列化為字串而不是日期時間?
編輯:
$val = '{ "date":"2022-09-30T07:04:23.571 00:00" }' | ConvertFrom-Json
$val.date.GetType().FullName
uj5u.com熱心網友回復:
這實際上是一個已知問題,請參閱:#13598Add a -DateKind parameter to ConvertFrom-Json to control how System.DateTime / System.DateTimeOffset values areConstructed。然而,我認為這沒有簡單的解決方案。您可能會做的一件事就是呼叫 (Windows) PowerShell。這目前也不是直截了當的,因此我創建了一個小包裝器來在 PowerShell 會話之間發送和接收復雜的物件(另請參閱我的#18460 Invoke-PowerShell目的):
function Invoke-PowerShell ($Command) {
$SerializeOutput = @"
`$Output = $Command
[System.Management.Automation.PSSerializer]::Serialize(`$Output)
"@
$Bytes = [System.Text.Encoding]::Unicode.GetBytes($SerializeOutput)
$EncodedCommand = [Convert]::ToBase64String($Bytes)
$PSSerial = PowerShell -EncodedCommand $EncodedCommand
[System.Management.Automation.PSSerializer]::Deserialize($PSSerial)
}
用法:
Invoke-PowerShell { '{ "date":"2022-09-30T07:04:23.571 00:00" }' | ConvertFrom-Json }
date
----
2022-09-30T07:04:23.571 00:00
更新
正如mklement0評論的那樣,我顯然使答案復雜化了。
通過 powershell.exe 呼叫是一種實用的解決方法(盡管速度慢且僅限 Windows),但請注意,您不需要輔助函式:如果您將腳本塊從 PowerShell傳遞給 powershell.exe(或 pwsh.exe),Based64基于 CLIXML 的序列化在幕后自動發生:嘗試
powershell.exe -noprofile { $args | ConvertFrom-Json } -args '{ "date":"2022-09-30T07:04:23.571 00:00" }'出于這個原因,我認為不需要 Invoke-PowerShell cmdlet。
$Json = '{ "date":"2022-09-30T07:04:23.571 00:00" }'
powershell.exe -noprofile { $args | ConvertFrom-Json } -args $Json
date
----
2022-09-30T07:04:23.571 00:00
uj5u.com熱心網友回復:
iRon 的有用答案通過Windows PowerShell CLI提供了一個實用的解決方案,
powershell.exe這依賴于ConvertFrom-Json不會自動將類似 ISO 8601 的時間戳字串轉換為實體的事實。[datetime]希望他鏈接到的 GitHub 問題#13598中的提案將在未來實施,然后將解決方案簡化為:
# NOT YET IMPLEMENTED as of PowerShell 7.2.x '{ "date":"2022-09-30T07:04:23.571 00:00" }' | ConvertFrom-Json -DateTimeKind None
但是,一種
powershell.exe解決方法有兩個缺點:(a) 它很慢(必須啟動子行程中的單獨 PowerShell 實體),以及 (b) 它僅適用于 Windows。下面的解決方案是您自己的方法的概括,可以避免這些問題。
這是您自己的行程內方法的概括:
它在與時間戳模式匹配的每個字串的開頭注入一個 NUL 字符 (
"`0") - 假設輸入本身從不包含此類字符,這是公平的假設。正如您的方法一樣,這可以防止
ConvertFrom-Json識別時間戳字串,并使它們保持不變。然后必須對輸出的
[pscustomobject]圖形進行后處理,以便再次洗掉注入的 NUL 字符。ConvertFrom-Json這是通過
ForEach-Object包含一個遞回遍歷物件圖的幫助腳本塊的呼叫來實作的,它的優點是它 可以與 JSON 輸入一起作業,其時間戳字串可能位于層次結構的任何級別(即它們也可能位于嵌套的屬性中物件)。注意:假設時間戳字串僅作為屬性值包含在輸入中;
'[ "2022-09-30T07:04:23.571 00:00" ]'如果您也想處理輸入 JSON,例如字串本身就是輸入物件,則需要做更多的作業。
# 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 -NoEnumerate |
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 {
$_
}
}
uj5u.com熱心網友回復:
根據@zett42 的輸入,我的解決方案是:
假設我們知道 JSON 中使用的日期的正則運算式模式,我將 JSON 作為字串,添加一個前綴,以便ConvertFrom-Json不將日期轉換為 datetime 而是將其保留為字串,將其轉換ConvertFrom-Json為 a PSCustomObject,做我需要做的任何事情物件,將其序列化回 JSON 字串,ConvertTo-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
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/528443.html
