Манипулирование метками времени объекта JSON

#arrays #json #powershell #foreach #convertto-json

Вопрос:

 {
    "logs":  [
                 {
                     "timestamp":  "20181216T14:36:12",
                     "description":  "IP connectivity via interface ipmp1 has become degraded.",
                     "type":  "alert",
                     "uuid":  "1234567",
                     "severity":  "Minor"
                 },
                 {
                     "timestamp":  "20181216T14:38:16",
                     "description":  "Network connectivity via port ibp4 has been established.",
                     "type":  "alert",
                     "uuid":  "12345678",
                     "severity":  "Minor"
                 }
             ]
}
 

У меня есть этот объект JSON, и я хочу перебрать каждый объект и обновить метку времени до более читаемой даты. Прямо сейчас у меня есть

 $currentLogs.logs |
Where{$_.type -eq 'alert'} |
ForEach{$_.timestamp = {[datetime]::parseexact($_.timestamp, 'yyyyMMddTHH:mm:ss', $null)}}
 

Но когда я прочитал объект $currentLogs, он все еще не обновился.

Комментарии:

1. Вы установили $_.timestamp блок сценария и никогда не выполняли блок сценария. Кроме того, вы только попытались проанализировать значение и не предоставили новый формат после анализа, если вы не хотите, чтобы формат по умолчанию применялся к типу данных вашего значения.

2. Удалите { } фигурные скобки после = окружения parseexact() команды в вашей ForEach{$_.timestamp = {[datetime]::parseexact(... строке

3. Каким был бы для вас формат «более читаемой даты» ?

4. @Тео хотел бы, чтобы он показывал «гггг-ММ-дд ЧЧ:мм:сс»

Ответ №1:

Вам нужно будет сначала проанализировать дату/время, а затем применить нужное форматирование. Если вы не примените форматирование, то timestamp свойство будет datetime типом объекта, и преобразование обратно в JSON приведет к странному форматированию. Было бы лучше сделать ваш новый формат строкой, чтобы он не подвергался манипуляциям при сериализации JSON:

 $currentLogs.logs | Where type -eq 'alert' | ForEach-Object {
    $_.timestamp = [datetime]::parseexact($_.timestamp, 'yyyyMMddTHH:mm:ss', $null).ToString('yyyy-MM-dd HH:mm:ss')
}
 

В своей попытке вы использовали следующий код:

 {[datetime]::parseexact($_.timestamp, 'yyyyMMddTHH:mm:ss', $null)}
 

Использование окружения {} обозначает блок сценария. Если этот блок сценария не вызывается или не вызывается, он просто выведет свое содержимое дословно. Вы можете запустить приведенный выше код в своей консоли и увидеть этот результат.

Вы также не отформатировали свой datetime объект после попытки синтаксического анализа. По умолчанию вывод в консоли будет применяться ToString() неявно, когда datetime значение задано свойству, но это неявное форматирование не преобразуется в преобразование JSON (по какой-либо причине).

Комментарии:

1. Здравствуйте, я реализовал этот блок кода, и он все еще дословно возвращает содержимое. Правильно ли я называю метку времени?

2. Убедитесь, что вы не используете {} вокруг своего [datetime]::parseexact() выражения.

Ответ №2:

Спасибо, что показали нужный формат.

Чтобы обновить те элементы, в которых » тип «равен » оповещению», вы можете сделать это:

 $json = @'
{
    "logs":  [
                 {
                     "timestamp":  "20181216T14:36:12",
                     "description":  "IP connectivity via interface ipmp1 has become degraded.",
                     "type":  "alert",
                     "uuid":  "1234567",
                     "severity":  "Minor"
                 },
                 {
                     "timestamp":  "20181216T14:38:16",
                     "description":  "Network connectivity via port ibp4 has been established.",
                     "type":  "alert",
                     "uuid":  "12345678",
                     "severity":  "Minor"
                 }
             ]
}
'@ | ConvertFrom-Json

# find the objects with 'type' equals 'alert'
$json.logs | Where-Object { $_.type -eq 'alert' } | ForEach-Object { 
    # parse the date in its current format
    $date = [datetime]::ParseExact($_.timestamp, 'yyyyMMddTHH:mm:ss', $null)
    # and write back with the new format
    $_.timestamp = '{0:yyyy-MM-dd HH:mm:ss}' -f $date
}

# convert back to json
$json | ConvertTo-Json
 

Если вы хотите сохранить в файл, добавьте последнюю строку выше с | Set-Content -Path 'X:PathToUpdated.json'