Proper formating of JSON using powershell Proper formating of JSON using powershell powershell powershell

Proper formating of JSON using powershell


Since your original json contains an array with only one element, PowerShell will condense that to become just this one element. If in your output you want it to be an array again, use rokumaru's good answer.

However, PowerShell's ConvertTo-Json does not produce pretty formatted json and for that I have written a helper function some time ago:

function Format-Json {    <#    .SYNOPSIS        Prettifies JSON output.    .DESCRIPTION        Reformats a JSON string so the output looks better than what ConvertTo-Json outputs.    .PARAMETER Json        Required: [string] The JSON text to prettify.    .PARAMETER Minify        Optional: Returns the json string compressed.    .PARAMETER Indentation        Optional: The number of spaces (1..1024) to use for indentation. Defaults to 4.    .PARAMETER AsArray        Optional: If set, the output will be in the form of a string array, otherwise a single string is output.    .EXAMPLE        $json | ConvertTo-Json  | Format-Json -Indentation 2    #>    [CmdletBinding(DefaultParameterSetName = 'Prettify')]    Param(        [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)]        [string]$Json,        [Parameter(ParameterSetName = 'Minify')]        [switch]$Minify,        [Parameter(ParameterSetName = 'Prettify')]        [ValidateRange(1, 1024)]        [int]$Indentation = 4,        [Parameter(ParameterSetName = 'Prettify')]        [switch]$AsArray    )    if ($PSCmdlet.ParameterSetName -eq 'Minify') {        return ($Json | ConvertFrom-Json) | ConvertTo-Json -Depth 100 -Compress    }    # If the input JSON text has been created with ConvertTo-Json -Compress    # then we first need to reconvert it without compression    if ($Json -notmatch '\r?\n') {        $Json = ($Json | ConvertFrom-Json) | ConvertTo-Json -Depth 100    }    $indent = 0    $regexUnlessQuoted = '(?=([^"]*"[^"]*")*[^"]*$)'    $result = $Json -split '\r?\n' |        ForEach-Object {            # If the line contains a ] or } character,             # we need to decrement the indentation level unless it is inside quotes.            if ($_ -match "[}\]]$regexUnlessQuoted") {                $indent = [Math]::Max($indent - $Indentation, 0)            }            # Replace all colon-space combinations by ": " unless it is inside quotes.            $line = (' ' * $indent) + ($_.TrimStart() -replace ":\s+$regexUnlessQuoted", ': ')            # If the line contains a [ or { character,             # we need to increment the indentation level unless it is inside quotes.            if ($_ -match "[\{\[]$regexUnlessQuoted") {                $indent += $Indentation            }            $line        }    if ($AsArray) { return $result }    return $result -Join [Environment]::NewLine}

Use it like this:

$json = Get-Content 'D:\script\test.json' -Encoding UTF8 | ConvertFrom-Json$json.yura.ContentManager.branch = 'test'# recreate the object as array, and use the -Depth parameter (your json needs 3 minimum)ConvertTo-Json @($json) -Depth 3 | Format-Json | Set-Content "D:\script\test1.json" -Encoding UTF8# instead of using '@($json)' you can of course also recreate the array by adding the square brackets manually:# '[{0}{1}{0}]' -f [Environment]::NewLine, ($json | ConvertTo-Json -Depth 3) | #        Format-Json | Set-Content "D:\script\test1.json" -Encoding UTF8


If the whole is an array and the element is a single json file, it is awkward.
If you use a pipeline, it is not treated as an array.

$json | ConvertTo-Json -Depth 10 # bad

and since it is not a normal array, so just passing it as a parameter won't work.

ConvertTo-Json $json -Depth 10  # bad

It works well if you re-create the array.

ConvertTo-Json @($json) -Depth 10  # good


I wrote the next function to fix the indentation

function FixJsonIndentation ($jsonOutput){    $currentIndent = 0    $tabSize = 4    $lines = $jsonOutput.Split([Environment]::NewLine)    $newString = ""    foreach ($line in $lines)    {        # skip empty line        if ($line.Trim() -eq "") {            continue        }        # if the line with ], or }, reduce indent        if ($line -match "[\]\}]+\,?\s*$") {            $currentIndent -= 1        }        # add the line with the right indent        if ($newString -eq "") {            $newString = $line        } else {            $spaces = ""            $matchFirstChar = [regex]::Match($line, '[^\s]+')                        $totalSpaces = $currentIndent * $tabSize            if ($totalSpaces -gt 0) {                $spaces = " " * $totalSpaces            }                        $newString += [Environment]::NewLine + $spaces + $line.Substring($matchFirstChar.Index)        }        # if the line with { or [ increase indent        if ($line -match "[\[\{]+\s*$") {            $currentIndent += 1        }    }    return $newString}