我已經從一個 REST API 中檢索了 json 日志資料,如下所示
[
{
"id": "6523276",
"type": "logs",
"attributes": {
"created-at": "2022-02-22T10:50:26Z",
"action": "delete",
"resource-name": "DocumentABC.docx",
"user-name": "Joe Smith"
}
},
{
"id": "6523275",
"type": "logs",
"attributes": {
"created-at": "2022-02-22T10:03:22Z",
"action": "create",
"resource-name": "Document123.docx",
"user-name": "Joe Smith"
}
},
{
"id": "6523274",
"type": "logs",
"attributes": {
"created-at": "2022-02-22T06:42:21Z",
"action": "open",
"resource-name": "123Document.docx",
"user-name": "Joe Smith"
}
}
]
我需要將 json 發布到另一個網路應用程式,但我只想要最后一小時的日志。在上面的 json 示例中,當前時間是 2022-02-22T10:55:22Z,因此我只對前兩個日志條目感興趣。
例如
[
{
"id": "6523276",
"type": "logs",
"attributes": {
"created-at": "2022-02-22T10:50:26Z",
"action": "delete",
"resource-name": "DocumentABC.docx",
"user-name": "Joe Smith"
}
},
{
"id": "6523275",
"type": "logs",
"attributes": {
"created-at": "2022-02-22T10:03:22Z",
"action": "create",
"resource-name": "Document123.docx",
"user-name": "Joe Smith"
}
}
]
這是我的 powershell v7 腳本
$json = $json | ConvertFrom-Json
$filterTime = (Get-date).AddHours(-1)
$RFCfilterTime = [Xml.XmlConvert]::ToString($filterTime,[Xml.XmlDateTimeSerializationMode]::Utc)
$Filteredjson = $json | Where-Object $json.attributes[0] -ge $RFCfilterTimefilterDate
$jsonToPost = ConvertTo-Json -InputObject @($Filteredjson) -Depth 5
問題是 ConvertFrom-Json 將 'created-at' 從 RFC3339 格式更改為 'datetime' 格式。因此 Where-Object 過濾器不起作用......
id type attributes
-- ---- ----------
6523276 logs @{created-at=22/02/2022 10:50:26 AM; action…
6523275 logs @{created-at=22/02/2022 10:03:22 AM; action…
6523274 logs @{created-at=22/02/2022 6:42:21 AM; action=…
如何將所有“created-at”物件改回 RCF3339 格式?
該
$json | Where-Object $json.attributes[0] -ge $RFCfilterTimefilterDate
陳述句是否被正確使用?
有沒有更簡單的方法?
uj5u.com熱心網友回復:
您的方法原則上應該有效,但您的Where-Object陳述存在問題 - 請參閱底部。
Mathias 的回答顯示了如何處理[datetime]由 ' 直接決議產生的實體ConvertTo-Json,但還需要做更多的作業:
實際上,在PowerShell (Core) v6
ConvertFrom-Json中(通過 JSON Web 服務隱式使用Invoke-RestMethod)會自動反序列化 ISO 8601 格式的日期時間字串,例如"2022-02-22T10:03:22Z"轉換為[datetime]System.DateTime實體,相反,在使用 (重新)序列化時ConvertTo-Json,[datetime]實體是(重新)轉換為 ISO 8601 字串。雖然這可以方便地與其他
[datetime]實體進行時間順序比較,例如回傳的Get-Date,但存在一個主要缺陷:只有[datetime]具有相同.Kind屬性值的實體才有意義地比較(可能的值是Local、Utc和Unspecified,后者在比較中被視為相同Local)。不幸的是,從 PowerShell 7.2.1 開始,您無法控制實體構造
.Kind的[datetime]Convert-FromJson內容 -識別為 ISO 8601 日期的每個字串的特定日期時間字串格式暗示了這一點。- 同樣,在使用 (重新)序列化時
ConvertTo-Json,該.Kind值確定字串格式。 - 有關詳細資訊,請參閱此答案。
- 同樣,在使用 (重新)序列化時
在您的情況下,由于您的日期時間字串具有Z表示 UTC 的后綴,因此構造[datetime]了帶有的實體.Kind Utc。
因此,您需要確保您的比較時間戳是 a Utc [datetime]too,呼叫輸出.ToUniversalTime()的Local實體可以Get-Date確保:
# Note the need for .ToUniversalTime()
$filterTime = (Get-Date).ToUniversalTime().AddHours(-1)
# Note: Only works as intended if all date-time strings are "Z"-suffixed
$filteredData = $data | Where-Object { $_.attributes.'created-at' -ge $filterTime }
但是,至少假設給定的 JSON 檔案可能包含不同的日期時間字串格式,從而導致不同 .Kind的值。
處理這種情況的方法 - 以及字串格式一致但不一定提前知道的情況 - 您可以使用通常更可取的[datetimeoffset]( System.DateTimeOffset) 型別,它會自動將時間戳識別為等效,即使它們的運算式(本地 vs .UTC) 不同:
# Note the use of [datetimeoffset]
[datetimeoffset] $filterTime = (Get-Date).AddHours(-1)
# With this approach the specific format of the date-time strings is irrelevant,
# as long as they're recognized as ISO 8601 strings.
$filteredData = $data |
Where-Object { [datetimeoffset] $_.attributes.'created-at' -ge $filterTime }
注意:嚴格來說,比較的LHS[datetimeoffset]是型別就足夠了-[datetime]然后也可以正確處理 RHS。
潛在的未來改進:
- GitHub issue #13598建議向 中添加一個
-DateTimeKind引數ConvertFrom-Json,以允許明確請求感興趣的型別,并交替構造[datetimeoffset]實體。
至于你嘗試了什么:
該
$json | Where-Object $json.attributes[0] -ge $RFCfilterTimefilterDate陳述句是否被正確使用?
不:
您使用的是簡化語法,其中比較的 LHS(
-Property引數)必須是每個輸入物件上直接可用的單個(非嵌套)屬性的名稱。因為在您的情況下需要嵌套屬性訪問,所以必須使用基于常規腳本塊的語法 (
{ ... }),在這種情況下,必須通過自動$_變數顯式參考手頭的輸入物件。.attributes[0]建議您嘗試通過 indexcreated-at訪問該屬性,但是 PowerShell 不支持該屬性;你需要:要么:拼出屬性的名稱,如果知道的話:
$_.attributes.'created-at'- 注意在這種情況下需要參考,因為使用了非標準-字符。在名字里。或:使用提供有關任何給定物件的反射資訊的內部
.psobject成員:$_.attributes.psobject.Properties.Value[0]
因此,通過拼出屬性名稱 - 并確保 LHS[datetime]值也表示為 ISO 8601 格式的字串,通過.ToString('o')- 您的陳述句應該是:
$json | Where-Object {
$_.attributes.'created-at'.ToString('o') -ge $RFCfilterTimefilterDate
}
uj5u.com熱心網友回復:
事實上,較新版本的ConvertFrom-Json隱式決議時間戳[datetime]實際上對您有利 -[datetime]值是可比較的,因此這僅意味著您可以跳過將閾值轉換為字串的步驟:
$data = $json | ConvertFrom-Json
$filterTime = (Get-Date).AddHours(-1)
$filteredData = $data | Where-Object {$_.attributes.'created-at' -ge $filterTime}
$jsonToPost = ConvertTo-Json -InputObject @($filteredData) -Depth 5
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/431212.html
