0
votes
{
    "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"
                 }
             ]
}

I have this JSON object, and I want to iterate through each object and update the timestamp to a more readable date. Right now, I have

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

But when I read the object $currentLogs, it still hasn't updated.

2
You set $_.timestamp to a script block and never executed the script block. Plus you have only attempted to parse the value and not supplied a new format after parsing unless you want the default format to be applied to your value's data type.AdminOfThings
Remove the { } braces after = surrounding the parseexact() command in your ForEach{$_.timestamp = {[datetime]::parseexact(... lineDaniel
What would be " a more readable date" format for you?Theo
@Theo Would like it to show 'yyyy-MM-dd HH:mm:ss'Francesca Suba

2 Answers

1
votes

You will need to first parse your date/time and then apply the formatting you want. If you apply no formatting, then the timestamp property will be a datetime object type and the conversion back to JSON will do weird formatting to it. It would be best to make your new format a string so that it won't be manipulated by the JSON serialization:

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

In your attempt, you used the following code:

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

The use of surrounding {} denotes a script block. If that script block is not called or invoked, it will just output its contents verbatim. You can run the above code in your console and see that result.

You also did not format your datetime object after the parse attempt. By default, the output in the console would apply a ToString() implicitly when the datetime value is set to a property, but that implicit formatting does not translate to your JSON conversion (for whatever reason).

0
votes

Thanks for showing the desired format.

To update those elements where the 'type' equals 'alert', you can do this:

$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

If you like to save to file, append the above last line with | Set-Content -Path 'X:\Path\To\Updated.json'