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
}
Примечание:
Необходимость обходного решения Windows PowerShell объясняется в этом ответе .
,
, оператор массива , оператор , используется здесь в его унарной форме, чтобы обеспечить вспомогательный одноэлементный массив wrapper в следующем порядке: отправить массив целиком (как один объект) по конвейеру; по умолчанию отправка массива (перечислимого) в конвейер отправляет его элементы один за другим ;обратите внимание, что это фундаментальное конвейерное поведение, независимо от используемых командлетов.
@(...)
, «массив-гарант» оператор (оператор подвыражения массива), гарантирует , что $_
является массивом , то есть он оборачивает операнд в массив, если он уже не равен единице (свободно говоря [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
switch , который напрямую обеспечивает сериализацию входных данных в виде массива, даже если существует только одиночный входной объект:
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
делает не действует как "гарант" массива, как @(...)
обсуждается в этой проблеме GitHub .
[1] Если операндом является скаляр (один объект), он заключен в один элемент [object[]]
;если операнд уже является массивом или перечислимым, элементы перечисляются и записываются в массив new [object[]]
.