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

6tdlim6h  于 2023-06-25  发布在  Shell
关注(0)|答案(2)|浏览(149)

观察:

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

72qzrwbm1#

注意事项:

  • 下面的答案讨论了通过管道 * 向ConvertTo-Json * 提供输入,以及使用 * 空 * 或 * 单元素 * 数组作为输入的陷阱,以及解决方法。
  • 正如js2010's helpful answer所示,如果将这样一个数组作为 * 参数 * 传递(例如,ConvertTo-Json (@1)),也在下面解释。
  • 对于 * pipeline * 输入,PowerShell (Core) 7+现在提供了方便的-AsArray交换机来解决这个问题,下面将讨论。

如果$val是空数组、标量或数组,**使用, @($val) | ConvertTo-Json**确保它被序列化为 * array *:

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 * operator**,在这里以其一元形式使用,以提供一个辅助的单元素 * wrapper * 数组,以便将数组 * 作为一个整体*(作为单个对象)通过管道发送;* * 默认情况下,将数组(可枚举)发送到流水线时,会将其元素 * 逐个发送***;注意,这是“基本的”流水线行为,而与所涉及的cmdlet无关。
      • @(...)"array-guarantee" 运算符(array-subexpression运算符),* 确保 * $_是一个 * array**,也就是说,它将操作数 Package 在数组中,除非它已经是一个(松散地说[1]);这对于涵盖$_只包含一个 * 单个 * 对象(标量; 1在这种情况下)。
      • 一般警告**:* * ConvertTo-Json默认悄悄地将其序列化深度限制为2**,会导致嵌套越深的输入会悄悄丢失数据;根据需要使用-Depth参数。
  • This SO post讨论了这个问题。
  • GiHub issue #8393要求更改危险的默认行为;虽然这并没有发生,但PowerShell 7+现在至少省略了一个 * warning *,然后发生截断。

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

[]
[
  1
]
[
  1,
  2
]

或者,你可以将输入作为 * arguments * 传递给ConvertTo-Json,使用@($val)

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

位置参数隐式绑定到-InputObject参数,该参数 * 不 * 枚举其参数,因此按原样绑定数组。因此,在本例中,您只需要“数组保证人”@()(不需要包含的 Package 数组)。

    • PowerShell * Core * 现在提供了-AsArray开关**,直接保证输入序列化为数组,即使只有 * 单个 * input对象:
PS> 1 | ConvertTo-Json -AsArray
[
  1
]

然而,考虑到空数组导致 * 没有 * 数据通过管道发送,如果输入是 * 空数组 *,那么仍然需要一个 Package 器数组,然后 * 必须 * 使用-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不像@(...)那样充当数组“担保人”,这在GitHub issue #10952中讨论过。
[1]如果操作数是 * scalar *(单个对象),则将其 Package 在单个元素[object[]]中;如果操作数已经是数组或可枚举的,则元素被枚举并捕获在 * new * [object[]]数组中。

biswetbf

biswetbf2#

最后,使用-InputObject:

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

convertto-json -InputObject @() 
[]

相关问题