json - 如何使用 ConvertTo-Json 将 powershell 数组转换为 json?

标签 json powershell

观察:

C:\> [array]@(1,2) | ConvertTo-Json
[
    1,
    2
]
C:\> [array]@(1) | ConvertTo-Json
1
C:\> [array]@() | ConvertTo-Json
C:\>

(我希望从最后两个案例中分别得到 [1] 和 [])

所以,如果我想使用标准 ConvertTo-Json方法,我如何可靠地做到这一点,即使数组包含 1 或 0 个元素?

请注意,当数组是转换为 json 的复杂对象的一部分时,对结果进行后处理是不可行的。

编辑 1
C:\> $PSVersionTable

Name                           Value
----                           -----
PSVersion                      5.1.17763.592
PSEdition                      Desktop
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...}
BuildVersion                   10.0.17763.592
CLRVersion                     4.0.30319.42000
WSManStackVersion              3.0
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1


C:\> [array]@(1) | ConvertTo-Json -AsArray
ConvertTo-Json : A parameter cannot be found that matches parameter name 'AsArray'.
At line:1 char:30
+ [array]@(1) | ConvertTo-Json -AsArray
+                              ~~~~~~~~
    + CategoryInfo          : InvalidArgument: (:) [ConvertTo-Json], ParameterBindingException
    + FullyQualifiedErrorId : NamedParameterNotFound,Microsoft.PowerShell.Commands.ConvertToJsonCommand

C:\>

最佳答案

PowerShell Core (v6+) 提供方便的 -AsArray开关,在底部讨论。

如果 $val是空数组、标量或数组 发送, @($val)ConvertTo-Json通过管道确保它被序列化为数组:

if (-not $IsCoreCLR) {  # Workaround for Windows PowerShell
 # Only needed once per session.
 Remove-TypeData -ErrorAction Ignore System.Array
}

# Send an empty array, a single object, and an array...
@(), 1, (1, 2) | ForEach-Object { 
  # ... and ensure that each input ($_) serializes as a JSON *array*.
  , @($_) | ConvertTo-Json 
}

笔记:
  • this answer 中解释了对 Windows PowerShell 解决方法的需求。 .
  • , , 数组构造运算符 , 在这里以一元形式使用,以提供辅助的单元素包装数组,以便 发送整个数组 (作为单个对象)通过管道; 默认情况下,将数组(可枚举)发送到管道会一一发送其元素 ;请注意,这是基本的管道行为,与涉及的 cmdlet 无关。
  • @(...) ,“数组保证”运算符(数组子表达式运算符),确保 $_是一个数组 ,也就是说,它将操作数包装在一个数组中,除非它已经是一个(松散地说[1]);这对于涵盖 $_ 的情况是必要的仅包含一个对象(标量;在本例中为 1)。
  • 一般警告 : ConvertTo-Json悄悄地将其序列化深度限制为 2默认 , 其中 使用更深的嵌套输入导致安静的数据丢失 ;使用 -Depth参数根据需要。
  • This SO post讨论问题。
  • This related GiHub issue要求改变危险的默认行为 - 如果您同意,请在那里听到您的声音。

  • 以上产生以下结果 - 请注意每个输入如何序列化为数组:

    []
    [
      1
    ]
    [
      1,
      2
    ]
    

    或者,您可以将输入作为参数传递给 ConvertTo-Json@($val) :
    # Same output as above.
    @(), 1, (1,2) | ForEach-Object { ConvertTo-Json @($_) }
    

    位置参数隐式绑定(bind)到 -InputObject参数,它不枚举其参数,因此按原样绑定(bind)数组。
    因此您只需要“数组保证人”@()在这种情况下(也不是带有 的包装器数组)。

    PowerShell Core 现在提供 -AsArray开关 ,它直接确保输入被序列化为一个数组,即使只有一个输入对象:
    PS> 1 | ConvertTo-Json -AsArray
    [
      1
    ]
    

    但是,鉴于空数组导致没有数据通过管道发送,您 如果输入是空数组,仍然需要一个包装器数组,然后你不能使用 -AsArray :
    # Note:
    #   @() | ConvertTo-Json -AsArray
    # would result in NO output.
    # Use `, ` to wrap the empty array to ensure it gets sent through
    # the pipeline and do NOT use -AsArray
    PS> , @() | ConvertTo-Json -Compress
    
    []
    

    或者,再次将空数组作为参数传递:
    PS> ConvertTo-Json @() -Compress # Do NOT use -AsArray
    
    []
    

    问题是 -AsArray无条件地将其输入包装在 JSON 数组中 ,以便再次包装已经是数组的东西:
    PS> ConvertTo-Json -AsArray @() -Compress
    
    [[]]  # *nested* empty arrays
    

    -AsArray不像 @(...) 那样充当数组“担保人”确实在 this GitHub issue 中进行了讨论.

    [1] 如果操作数是标量(单个对象),则将其包裹在单个元素中 [object[]] ;如果操作数已经是一个数组或者是一个可枚举的,这些元素被枚举并捕获在一个新的[object[]]中。大批。

    关于json - 如何使用 ConvertTo-Json 将 powershell 数组转换为 json?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58617070/

    相关文章:

    java - JSONObject getString(String.valueof(variable integer)) 不工作

    powershell - 具有相对文件路径的 PowerShell(或 CMD)中的 md5 哈希

    powershell - 将 "Visual Studio code"与交互式 Powershell 窗口(如 Powershell ISE)结合使用

    java - Spring 5 MVC JSON ser/deser 不尊重属性(但适用于 XML)

    powershell - 如何在PowerShell中定义子例程

    powershell - 带有远程 session 的调用命令:无法验证参数上的参数

    function - Powershell Out-Host -paging -or- more 来限制函数的输出

    javascript - 无法访问 JSON 对象数组中的元素

    java - 带有 gradle 的 Jersey 测试框架 - MessageBodyProviderNotFound

    php - javascript 不通过 php 代码发送数据