Home > Blockchain >  How to join the value of two variables in the output of the command to convert in json mode with Pow
How to join the value of two variables in the output of the command to convert in json mode with Pow

Time:04-12

with powershell I can get, with just one line (prerequisite) and using foreach, the date of last update of the folders and the difference in days, however, I need to get this information in a format for use via json and I can't display the value of $pasta with the value of $DiasV why when converting with "| convertto-Json" the result is not in the correct format (I'm validating via https://jsonformatter.org/json-parser).

foreach ($pasta in Get-ChildItem -Path C:\TEMP\ -Directory) 
{
$ErrorActionPreference = 'SilentlyContinue';
$path = 'C:\TEMP\'   $pasta   '\EXAMPLE';
$start = Get-ChildItem -Path $path -File | Sort-Object -Property CreationTime | Select-Object -ExpandProperty LastWriteTime -Last 1;
$end = Get-Date; $DiasV = (New-TimeSpan -Start $start -End $end);
write $pasta.Name $pasta.LastWriteTime $DiasV.Days | ConvertTo-Json 
}

Output:

[
    "A123_1A_CAB",
    {
        "value":  "\/Date(1649508388226)\/",
        "DateTime":  "sábado, 9 de abril de 2022 09:46:28"
    },
    0
]
[
    "C166_5AND_BBB",
    {
        "value":  "\/Date(1649610666329)\/",
        "DateTime":  "domingo, 10 de abril de 2022 14:11:06"
    },
    2
]

My intention is to get this output:

[
    {
        "pasta":  "A123_1A_CAB"
        "value":  "\/Date(1649508388226)\/",
        "DateTime":  "sábado, 9 de abril de 2022 09:46:28"
        "Dias":  "0"
    },
    {
        "pasta":  "C166_5AND_BBB"
        "value":  "\/Date(1649610666329)\/",
        "DateTime":  "domingo, 10 de abril de 2022 14:11:06"
        "Dias":  "2"
    }
]

I need help to solve this, already tried several ways without success.I'm still learning english.

CodePudding user response:

Your primary problem is that you want the output to be converted to a single JSON array:

  • By placing your ConvertTo-Json call inside your foreach loop, you're creating a separate JSON document in each iteration, which when combined as-is result in malformed JSON.

  • Simply apply ConvertTo-Json to all your output objects, across all loop iterations instead; this is more easily accomplished if you switch to a single pipeline that uses the
    ForEach-Object cmdlet.

  • Additionally, you need to encapsulate the pieces of information to report for each directory in an object whose properties contain the information:

To put it all together, with some optimizations:

Get-ChildItem -Path C:\TEMP\ -Directory |
  ForEach-Object { 
    $ErrorActionPreference = 'SilentlyContinue';
    $path = $_.FullName   '\EXAMPLE';
    $start = Get-ChildItem -LiteralPath $path -File | 
               Sort-Object -Property CreationTime |
                 Select-Object -ExpandProperty LastWriteTime -Last 1;
    $end = Get-Date; $DiasV = ($end - $start).Days;
    # Create a helper object for the "value" and "DateTime" properties. 
    $dateTimeCustom = $_.LastWriteTime | ConvertTo-Json | ConvertFrom-Json
    # Output the pieces of information encapsulated in an object.
    [pscustomobject] @{ 
      pasta = $_.Name;
      value = $dateTimeCustom.value;
      DateTime = $dateTimeCustom.DateTime;
      Dias = $DiasV
    }
} | ConvertTo-Json 

Note:

  • The only reason I've kept the ; at the end of the statements is to facilitate transforming the code into a single line. As written, the ; are not necessary.

  • Your output implies that you're using Windows PowerShell, where ConvertTo-Json serializes [datetime] values as objects with two or three properties, .value (a custom string representation based on the Unix epoch time representation, e.g., "\/Date(1649508388226)\/"), .DateTime, a friendly display string, and - if the [datetime] instance was obtained via Get-Date - additionally a .DisplayHint property.

    • To "flatten" these properties and make them direct properties of the output objects, a round-trip JSON conversion is used to create a helper object with those property values ($dateTimeCustom = $_.LastWriteTime | ConvertTo-Json | ConvertFrom-Json).

      • Strictly speaking, that ConvertTo-Json in Windows PowerShell produces an object with properties for a [datetime] instance - instead of just a single string such as "\/Date(1649508388226)\/" - should be considered a bug, not least because round-tripping such an object does not result in a [datetime] instance, but in a [pscustomobject] instance with properties .value and .DateTime and situationally also .DisplayHint (which we take advantage of here).

      • The problem occurs, because [datetime] instances are decorated with a type-level ETS ScriptProperty member, .DateTime, which, unfortunately, is included in the serialization, resulting in the two-property object representation at hand. If you were to remove the type data associated with [datetime], the problem would go away (but so would the property), e.g.:

        # Windows PowerShell only.
        # Note that if you were to use Get-Date output, *another*,
        # instance-level ETS property would come into play, .DisplayHint
        PS> Remove-TypeData System.DateTime; [datetime]::now | ConvertTo-Json
        "\/Date(1649702531387)\/"  # e.g. - single string
        
  • Note that PowerShell (Core) 7 no longer uses this custom-object representation and instead serializes [datetime] instances as strings in ISO 8601 date-time format (e.g., "2021-10-11T13:27:12.3318432-04:00")

  • Related