在 Powershell 中转换为 JSON 时如何更改制表符宽度

How to change tab width when converting to JSON in Powershell

我正在 Powershell 中创建一个 JSON,我想在构建它时设置自定义制表符宽度(而不是默认的 4 个空格,我只想设置 2 个空格)。

我这样做是因为:

示例代码:

$object = New-Object PSObject
Add-Member -InputObject $object -MemberType NoteProperty -Name Phone -Value "SomePhone"
Add-Member -InputObject $object -MemberType NoteProperty -Name Description -Value "Lorem ipsum dolor.."
Add-Member -InputObject $object -MemberType NoteProperty -Name Price -Value 99.99

$object | ConvertTo-Json

Result with tab width = 4 white space characters.

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

I tried compression but it doesn't give control over compression level (how agressive compression should be)

$object | ConvertTo-Json -Compress

Result compressed, obviously.

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

What I am trying to achieve: result with tab width = 2 white space characters.

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

What I've tried so far is in the pseudo code below. I'm still in the loop. Please get me out of there :)

while (1) {
    Google, Whosebug
    Try Stuff found 
    Tweak stuff found

    if (Correct answer) {
        break
    }
}

以下代码将缩进大小减半:

$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"

这里有一个简单的方法:

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

如果您将多个对象传递给 ConvertTo-JSON.

,则 foreach-object 会捕获

"`t" 更改为您想要的缩进。

因为 PowerShell 的 ConvertTo-Json 产生不确定的缩进,当前的答案不会产生 JSON 数据结构中的每个深度恰好有两个空格。

要使嵌套数据的每个级别比封闭级别多缩进两个空格,需要重建缩进。 (对于它的价值,在 PowerShell 6 中看起来像 this was fixed

写完我自己的解决方案后,我在 GitHub 上找到了一个几乎相同的解决方案,来自 Facebook 的 Daniel Lo Nigro (Daniel15) here。他是一个可以接受管道输入的 PowerShell 函数。 (我使正则表达式匹配更具体一些,以减少意外匹配数据的可能性。)

# 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 '":  (["{[])', '": ' -replace ':  ', ': ')
        if ($_ -match '[\{\[]\s*$') {
            # This line ends with [ or {, increment the indentation level
            $indent++
        }
        $line
    }) -Join "`n"
}

用法:$foo | ConvertTo-Json | Format-Json

您可以将 Newtonsoft.Json 与 PowerShell 一起使用。您可以安装 a module for it in PowerShell Gallery 以方便地使用它。

示例:

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()

生产

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

与 json 一起使用时,它还有大量其他功能:https://www.newtonsoft.com/json/help/html/Introduction.htm