【问题标题】:How to convert powershell array to json using ConvertTo-Json?如何使用 ConvertTo-Json 将 powershell 数组转换为 json?
【发布时间】:2019-10-30 00:11:32
【问题描述】:

观察:

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:\>

【问题讨论】:

  • 使用-AsArray 开关。
  • 好指针,@AdminOfThings,但值得指出的是,-AsArray 仅在 PowerShell Core 中受支持;另请注意,对于空数组,它不会像预期的那样工作:例如,ConvertTo-Json -AsArray @() -Compress 产生 [[]]

标签: json powershell


【解决方案1】:

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 解决方法的需求。

  • ,array-construction 运算符,在这里以一元形式使用,以提供辅助的单元素 包装器 数组,以便通过管道将数组作为一个整体(作为单个对象)发送; 默认情况下,向管道发送一个数组(可枚举)一个接一个地发送其元素;请注意,这是基本管道行为,与涉及的 cmdlet 无关。

  • @(...)"array-guarantor" 运算符(数组子表达式运算符),确保 $_ 是一个array,也就是说,它将操作数包装在一个数组中,除非它已经是一个(松散地说[1]);这对于覆盖$_ 仅包含一个单个 对象(标量;在这种情况下为1)的情况是必要的。

  • 一般警告ConvertTo-Json 默认情况下将其序列化深度限制为2,这会导致更深嵌套输入的安静数据丢失;根据需要使用-Depth 参数。

上面的结果如下——注意每个输入是如何被序列化为一个数组的:

[]
[
  1
]
[
  1,
  2
]

或者,您可以将输入作为参数传递给ConvertTo-Json @($val)

# Same output as above.
@(), 1, (1,2) | ForEach-Object { ConvertTo-Json @($_) }

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


PowerShell Core 现在提供了一个-AsArray 开关,它直接确保输入被序列化为一个数组,即使只有一个单个 em> 输入对象:

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[]]中;如果操作数已经是数组或者是可枚举的,则枚举元素并将其捕获到 new [object[]] 数组中。

【讨论】:

    【解决方案2】:

    最后,-InputObject 的用法:

    convertto-json -InputObject @(1)
    [
      1
    ]
    
    convertto-json -InputObject @() 
    []
    

    【讨论】:

    • 是的,绑定到-InputObject会阻止管道默认执行的数组枚举;请注意,在这种情况下-InputObject 绑定位置,因此您无需指定-InputObject(这就是我在回答中省略的原因);例如,ConvertTo-Json @() 可以。
    猜你喜欢
    • 1970-01-01
    • 2013-07-12
    • 2021-11-30
    • 1970-01-01
    • 2015-08-23
    • 1970-01-01
    • 2021-12-31
    • 2016-12-24
    • 2021-05-20
    相关资源
    最近更新 更多