观察:
C:\> [array]@(1,2) | ConvertTo-Json
[
1,
2
]
C:\> [array]@(1) | ConvertTo-Json
1
C:\> [array]@() | ConvertTo-Json
C:\>
Run Code Online (Sandbox Code Playgroud)
(我希望分别来自最后两个案例的 [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:\>
Run Code Online (Sandbox Code Playgroud)
最后,-InputObject 的用途:
convertto-json -InputObject @(1)
[
1
]
convertto-json -InputObject @()
[]
Run Code Online (Sandbox Code Playgroud)
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
}
Run Code Online (Sandbox Code Playgroud)
笔记:
此答案中解释了对 Windows PowerShell 解决方法的需求。
,,数组构造运算符,在此处以其一元形式使用,以提供辅助的单元素包装器数组,以便通过管道将数组作为一个整体(作为单个对象)发送;默认情况下,将数组(可枚举)发送到管道会一一发送其元素;请注意,这是基本的管道行为,与所涉及的 cmdlet 无关。
@(...),“数组保证”运算符(数组子表达式运算符),确保它$_是一个数组,也就是说,它将操作数包装在一个数组中,除非它已经是一个(松散地说[1]);这对于涵盖$_仅包含单个对象(标量;1在这种情况下)的情况是必要的。
一般警告:默认情况下ConvertTo-Json悄悄地将其序列化深度限制为2,这会导致嵌套更深的输入安静地丢失数据;-Depth根据需要使用参数。
这个SO帖子讨论了这个问题。
这个相关的 GiHub 问题要求更改危险的默认行为 - 如果您同意,请在那里听到您的声音。
以上产生以下结果 - 请注意每个输入是如何序列化为数组的:
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
}
Run Code Online (Sandbox Code Playgroud)
或者,您可以将输入作为参数传递给ConvertTo-Json
with@($val):
# Same output as above.
@(), 1, (1,2) | ForEach-Object { ConvertTo-Json @($_) }
Run Code Online (Sandbox Code Playgroud)
位置参数隐式绑定到-InputObject参数,该参数不枚举其参数,因此按原样绑定数组。因此,@()在这种情况下,您只需要“数组保证器” (也不是带有 的包装器数组, )。
PowerShell的核心现在提供一个-AsArray开关,它直接保证输入被序列作为阵列,即使只有一个单一的输入对象:
PS> 1 | ConvertTo-Json -AsArray
[
1
]
Run Code Online (Sandbox Code Playgroud)
但是,鉴于空数组导致没有数据通过管道发送,如果输入是空数组,则-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
[]
Run Code Online (Sandbox Code Playgroud)
或者,再次将空数组作为参数传递:
PS> ConvertTo-Json @() -Compress # Do NOT use -AsArray
[]
Run Code Online (Sandbox Code Playgroud)
问题是-AsArray 无条件地将它的输入包装在一个 JSON 数组中,这样已经是一个数组的东西又被包装了:
PS> ConvertTo-Json -AsArray @() -Compress
[[]] # *nested* empty arrays
Run Code Online (Sandbox Code Playgroud)
这-AsArray并不像此 GitHub 问题中讨论的那样充当数组“担保人” 。@(...)
[1] 如果操作数是标量(单个对象),则包裹在单个元素中[object[]];如果操作数已经是一个数组或者是一个可枚举的,元素被枚举并捕获到一个新 [object[]]数组中。
| 归档时间: |
|
| 查看次数: |
2414 次 |
| 最近记录: |