使用 powershell 正确格式化 JSON [英] Proper formating of JSON using powershell

查看:160
本文介绍了使用 powershell 正确格式化 JSON的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下 JSON 格式的文件:

ConvertTo-JSON 之前:

<预><代码>[{尤拉":{收银员":{"branch": "release/Retail-v4.0","configuration": "零售演示调试","datetime_deployed": "2018 年 4 月 18 日 07:45:05","deployed_by": "匿名","host": "cashier2-retail4.testing.aws.com","job": "http://jenkins-testing.aws.com:8080/job/CashierDeployment","lineserver": "","消息总线": "","product": "收银员","publish_profile": "cashier2.retail.dev.pubxml"},内容管理者": {"branch": "release/Retail-v3.31.1","configuration": "零售演示调试","datetime_deployed": "2018 年 1 月 17 日 11:59:24","deployed_by": "匿名","host": "contentmanager2-retail3.testing.aws.com","job": "http://jenkins-testing.aws.com:8080/job/ContentManagerDeployment","lineserver": "","消息总线": "","product": "ContentManager","publish_profile": "..\ContentManager.PublishProfiles\contentmanager2.retail5.dev.pubxml"}}}]

使用此代码操作数据后:

$json = Get-Content 'D:script	est.json' -encoding utf8 |ConvertFrom-Json$json.yura.ContentManager.branch = '测试'

我将 JSON 保存到另一个文件中:

$json |转换为json |设置内容 "D:script	est1.json" - 编码 utf8

问题是,保存文件后,格式变坏了:

<代码>{尤拉":{收银员":{"branch": "release/Retail-v4.0","configuration": "零售演示调试","datetime_deployed": "2018 年 4 月 18 日 07:45:05","deployed_by": "匿名","host": "cashier2-retail4.testing.aws.com","job": "http://jenkins-testing.aws.com:8080/job/CashierDeployment","lineserver": "","消息总线": "","product": "收银员","publish_profile": "cashier2.retail.dev.pubxml"},内容管理者":  {分支":测试","configuration": "零售演示调试","datetime_deployed": "2018 年 1 月 17 日 11:59:24","deployed_by": "匿名","host": "contentmanager2-retail3.testing.aws.com","job": "http://jenkins-testing.aws.com:8080/job/ContentManagerDeployment","lineserver": "","消息总线": "","product": "ContentManager","publish_profile": "..\ContentManager.PublishProfiles\contentmanager2.retail5.dev.pubxml"}}}

我的问题是 - 如何在 PowerShell 中保留源格式?

解决方案

由于您的原始 json 包含一个只有一个元素的数组,PowerShell 会将其压缩为仅此一个元素.如果在您的输出中您希望它再次成为数组,请使用 rokumaru 的好答案.

但是,PowerShell 的 ConvertTo-Json 不会生成格式漂亮的 json,为此我前段时间编写了一个辅助函数:

函数格式-Json {<#.概要美化 JSON 输出..描述重新格式化 JSON 字符串,使输出看起来比 ConvertTo-Json 输出更好..PARAMETER JSON必需:[字符串] 要美化的 JSON 文本..PARAMETER 缩小可选:返回压缩后的 json 字符串..PARAMETER 缩进可选:用于缩进的空格数 (1..1024).默认为 4..PARAMETER 数组可选:如果设置,则以字符串数组的形式输出,否则输出单个字符串..例子$json |ConvertTo-Json |格式-Json-缩进2#>[CmdletBinding(DefaultParameterSetName = 'Prettify')]参数([参数(强制 = $true,位置 = 0,ValueFromPipeline = $true)][字符串]$Json,[参数(参数集名称 = '缩小')][开关]$缩小,[参数(参数集名称 = '美化')][验证范围(1, 1024)][int]$缩进 = 4,[参数(参数集名称 = '美化')][开关]$AsArray)如果($PSCmdlet.ParameterSetName -eq 'Minify'){返回 ($Json | ConvertFrom-Json) |ConvertTo-Json -Depth 100 -Compress}# 如果输入 JSON 文本已使用 ConvertTo-Json -Compress 创建# 那么我们首先需要在不压缩的情况下重新转换它if ($Json -notmatch '
?
') {$Json = ($Json | ConvertFrom-Json) |ConvertTo-Json -Depth 100}$indent = 0$regexUnlessQuoted = '(?=([^"]*"[^"]*")*[^"]*$)'$result = $Json -split '
?
' |ForEach-Object {# 如果该行包含 ] 或 } 字符,# 我们需要减少缩进级别,除非它在引号内.if ($_ -match "[}]]$regexUnlessQuoted") {$indent = [Math]::Max($indent - $Indentation, 0)}# 用:"替换所有冒号-空格组合,除非它在引号内.$line = (' ' * $indent) + ($_.TrimStart() -replace ":s+$regexUnlessQuoted", ':')# 如果该行包含 [ 或 { 字符,# 我们需要增加缩进级别,除非它在引号内.if ($_ -match "[{[]$regexUnlessQuoted") {$indent += $Indentation}$行}if ($AsArray) { 返回 $result }返回 $result -Join [Environment]::NewLine}

像这样使用它:

$json = Get-Content 'D:script	est.json' -Encoding UTF8 |ConvertFrom-Json$json.yura.ContentManager.branch = '测试'# 将对象重新创建为数组,并使用 -Depth 参数(您的 json 至少需要 3 个)ConvertTo-Json @($json) -Depth 3 |格式-Json |Set-Content "D:script	est1.json" -Encoding UTF8# 除了使用 '@($json)' 您当然也可以通过手动添加方括号来重新创建数组:# '[{0}{1}{0}]' -f [Environment]::NewLine, ($json | ConvertTo-Json -Depth 3) |# 格式-Json |Set-Content "D:script	est1.json" -Encoding UTF8

I have a following file in JSON format:

Before ConvertTo-JSON:

[
    {
        "Yura": {
            "Cashier": {
                "branch": "release/Retail-v4.0",
                "configuration": "RetailDemo Debug",
                "datetime_deployed": "Apr 18 2018 07:45:05",
                "deployed_by": "anonymous",
                "host": "cashier2-retail4.testing.aws.com",
                "job": "http://jenkins-testing.aws.com:8080/job/CashierDeployment",
                "lineserver": "",
                "messagebus": "",
                "product": "Cashier",
                "publish_profile": "cashier2.retail.dev.pubxml"
            },
            "ContentManager": {
                "branch": "release/Retail-v3.31.1",
                "configuration": "RetailDemo Debug",
                "datetime_deployed": "Jan 17 2018 11:59:24",
                "deployed_by": "anonymous",
                "host": "contentmanager2-retail3.testing.aws.com",
                "job": "http://jenkins-testing.aws.com:8080/job/ContentManagerDeployment",
                "lineserver": "",
                "messagebus": "",
                "product": "ContentManager",
                "publish_profile": "..\ContentManager.PublishProfiles\contentmanager2.retail5.dev.pubxml"
            }
        }
    }
]

after using this code for manipulation with data:

$json = Get-Content 'D:script	est.json'  -encoding utf8 | ConvertFrom-Json
$json.yura.ContentManager.branch = 'test'

I save JSON into another file:

$json | convertto-json | set-content "D:script	est1.json" -encoding utf8

Problem is, that after saving file, format become broken:

{
    "Yura":  {
                 "Cashier":  {
                                 "branch":  "release/Retail-v4.0",
                                 "configuration":  "RetailDemo Debug",
                                 "datetime_deployed":  "Apr 18 2018 07:45:05",
                                 "deployed_by":  "anonymous",
                                 "host":  "cashier2-retail4.testing.aws.com",
                                 "job":  "http://jenkins-testing.aws.com:8080/job/CashierDeployment",
                                 "lineserver":  "",
                                 "messagebus":  "",
                                 "product":  "Cashier",
                                 "publish_profile":  "cashier2.retail.dev.pubxml"
                             },
                 "ContentManager":  {
                                        "branch":  "test",
                                        "configuration":  "RetailDemo Debug",
                                        "datetime_deployed":  "Jan 17 2018 11:59:24",
                                        "deployed_by":  "anonymous",
                                        "host":  "contentmanager2-retail3.testing.aws.com",
                                        "job":  "http://jenkins-testing.aws.com:8080/job/ContentManagerDeployment",
                                        "lineserver":  "",
                                        "messagebus":  "",
                                        "product":  "ContentManager",
                                        "publish_profile":  "..\ContentManager.PublishProfiles\contentmanager2.retail5.dev.pubxml"
                                    }
             }
}

My question is - how to preserve source formatting in 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 '
?
') {
        $Json = ($Json | ConvertFrom-Json) | ConvertTo-Json -Depth 100
    }

    $indent = 0
    $regexUnlessQuoted = '(?=([^"]*"[^"]*")*[^"]*$)'

    $result = $Json -split '
?
' |
        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	est.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	est1.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	est1.json" -Encoding UTF8

这篇关于使用 powershell 正确格式化 JSON的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆