How to change tab width when converting to JSON in Powershell

守給你的承諾、 提交于 2019-12-03 02:40:59

The following code will halve the size of indent:

$json = @"
{
    "Phone":  "SomePhone",
    "Description":  "Lorem ipsum dolor..",
    "Price":  99.99
}
"@

($json -split '\r\n' |
% {
  $line = $_
  if ($_ -match '^ +') {
    $len  = $Matches[0].Length / 2
    $line = ' ' * $len + $line.TrimStart()
  }
  $line
}) -join "`r`n"

Because the PowerShell's ConvertTo-Json produces non-deterministic indentation, the current answers will not produce JSON that has exactly two spaces for each depth in the data structure.

To get each level of nested data indented exactly two spaces more than the enclosing level requires rebuilding the indentation. (For what it's worth, looks like this was fixed in PowerShell 6)

After writing up my own solution, I found an almost identical one on GitHub, from Facebook's Daniel Lo Nigro (Daniel15) here. His is a PowerShell function that can take piped input. (I made the regex matches a bit more specific to reduce the likelihood of unintentional matching data.)

# Formats JSON in a nicer format than the built-in ConvertTo-Json does.
function Format-Json([Parameter(Mandatory, ValueFromPipeline)][String] $json) {
    $indent = 0;
    ($json -Split "`n" | % {
        if ($_ -match '[\}\]]\s*,?\s*$') {
            # This line ends with ] or }, decrement the indentation level
            $indent--
        }
        $line = ('  ' * $indent) + $($_.TrimStart() -replace '":  (["{[])', '": $1' -replace ':  ', ': ')
        if ($_ -match '[\{\[]\s*$') {
            # This line ends with [ or {, increment the indentation level
            $indent++
        }
        $line
    }) -Join "`n"
}

Usage: $foo | ConvertTo-Json | Format-Json

msftrncs

Here is a simple method:

$data_json | convertto-json -depth 100 |
    foreach-object {$_ -replace "(?m)  (?<=^(?:  )*)", "`t" } |
    set-content 'output.json'

The foreach-object catches if you pass more than one object to ConvertTo-JSON.

Change the "`t" to what ever you want to do with the indent.

You can use Newtonsoft.Json with PowerShell. There is a module for it in PowerShell Gallery that you can install to make it available in a convenient way.

Example:

if (!(Get-Module -ListAvailable -Name "newtonsoft.json")) {
    Install-Module -Name "newtonsoft.json" -Scope CurrentUser -Force
}

Import-Module "newtonsoft.json" -Scope Local

$JObject = [Newtonsoft.Json.Linq.JObject]::new(
    [Newtonsoft.Json.Linq.JProperty]::new("Phone", "SomePhone"),
    [Newtonsoft.Json.Linq.JProperty]::new("Description", "Lorem ipsum dolor.."),
    [Newtonsoft.Json.Linq.JProperty]::new("Price", 99.99));

$JObject.ToString()

Produces

{
  "Phone": "SomePhone",
  "Description": "Lorem ipsum dolor..",
  "Price": 99.99
}

It has tons of other features when working with json as well: https://www.newtonsoft.com/json/help/html/Introduction.htm

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!