Search code examples
jsonpowershellpretty-print

JSON formatting, either from file or variable


I have a PS script, which get JSON in variable ant then saves it in file.

Unfortunately, it get value in one string, like this:

{   "persistentdataapi": "https://somevalue.azurewebsites.net/",   "collectioncountapi": "https://anothervalue.azurewebsites.net/",   "eventserviceapi": "https://thirdvalue.azurewebsites.net/",   "securityserviceapi": "https://fourthvalue.azurewebsites.net/" }

Is there any way, to process this value through some (preferably PS) JSON formatting, to get this one:

{
"persistentdataapi": "https://somevalue.azurewebsites.net/",
"collectioncountapi": "https://anothervalue.azurewebsites.net/",
"eventserviceapi": "https://thirdvalue.azurewebsites.net/",
"securityserviceapi": "https://fourthvalue.azurewebsites.net/",
}

Code to get value in Jenkins:

Import-Module "C:\Program Files\WindowsPowerShell\Modules\Octopus-Cmdlets\0.4.4\Octopus-Cmdlets.psd1"

connect-octoserver http://internal-Octopus.azure.com:8082 API-123456789012345678
$raw = (Get-OctoVariable var.Portal.Web DataAPIJson | Where-Object { $_.Environment -eq "QA" } )

$raw.Value | Out-File "$env:WORKSPACE\portal\var.Portal.Web\dataapi.json"

Solution

  • Powershell by default pretty-prints any JSON it produces.

    So the correct way to do pretty-printing is to parse the JSON string into an object, and immediately convert it back to a JSON string.

    $json = '{   "persistentdataapi": "https://somevalue.azurewebsites.net/",   "collectioncountapi": "https://anothervalue.azurewebsites.net/",   "eventserviceapi": "https://thirdvalue.azurewebsites.net/",   "securityserviceapi": "https://fourthvalue.azurewebsites.net/" }'
    
    $json | ConvertFrom-Json | ConvertTo-Json
    

    produces

    {
        "persistentdataapi":  "https://somevalue.azurewebsites.net/",
        "collectioncountapi":  "https://anothervalue.azurewebsites.net/",
        "eventserviceapi":  "https://thirdvalue.azurewebsites.net/",
        "securityserviceapi":  "https://fourthvalue.azurewebsites.net/"
    }
    

    or in your case

    $file = "$env:WORKSPACE\portal\var.Portal.Web\dataapi.json"
    $raw.Value | ConvertFrom-Json | ConvertTo-Json | Out-File $file -Encoding UTF8
    

    As a side-effect this also makes sure that the JSON in the file is valid, because otherwise ConvertFrom-Json will throw an error.

    Please always explicitly specify UTF8 encoding when reading and writing JSON files.

    $data = Get-Content $file -Encoding UTF8 | ConvertFrom-Json
    
    $data | ConvertTo-Json | Set-Content $file -Encoding UTF8
    

    The reason for that is

    • By widely-accepted convention, JSON files ought to be UTF8.
    • Unless specified otherwise, Get-Content and Set-Content will use the system's default encoding to read/write text files.
    • The system default is very seldom UTF-8, most of the time it will be a legacy single-byte encoding like Windows-1252.
    • This creates the risk of
      • mangling Unicode characters, which are legal in JSON, when reading a JSON file.
      • creating JSON files that are not UTF-8, making them hard to consume by others.

    In fact, always specify an encoding explicitly when working with text files, not only in the case of JSON.