2016-03-18 2 views
0

У меня проблема в PowerShell, где 1-элементный массив, возвращаемый функцией, не возвращается в виде массива. Я нашел несколько мест, где были заданы подобные вопросы (PowerShell: How can I to force to get a result as an Array instead of Object & How can I force Powershell to return an array when a call only returns one object?), но решения там не работают для меня. Вот мой код:возвращает один объект из функции в виде массива

function x() 
{ 
    $levelMappings = @() 
    $levelMappings += @{"a"="b";"c"="d"} 
    return @($levelMappings) 
} 
(x).gettype().name 

возвращает

Hashtable

Я не хочу этого, я хочу, чтобы вещь, которая получает возвращенное всегда быть массив, даже если это только имеет в нем один элемент. Я знаю, что я могу обойти это явно преобразовать возвращаемое значение функции в массив:

function x() 
{ 
    $levelMappings = @() 
    $levelMappings += @{"a"="b";"c"="d"} 
    return @($levelMappings) 
} 
@(x).gettype().name 

, но я не хочу, чтобы сделать это. Я хочу, чтобы функция надежно возвращала массив каждый раз.


Ответы на более ранний проект этого вопроса посоветовал мне использовать унарный оператор, который работал лакомство за исключением, что, когда я труба результат к ConvertTo-Json (который, в конечном счете то, что мне нужно сделать) то я не получаю желаемого результата. Обратите внимание:

function x() 
{ 
    $levelMappings = @() 
    $levelMappings += @{"a"="b";"c"="d"} 
    $levelMappings += @{"e"="f";"g"="h"} 
    return ,$levelMappings 
} 
(x).gettype().name 
x | ConvertTo-Json 

После запуска его результат является:

{
"значение": [
{
"с": "д",
"а": " б»
}, {

"г": "ч",
"е": "е"
}
],
"Граф": 2
}

Как вы можете видеть объект я serialising в JSON был обернут внутри объекта JSON value, и теперь у меня есть объект count. Это не то, что я хочу. Любой способ решить это?


Другое обновление. Я обнаружил, что могу заключить вызов функции в круглые скобки, и, похоже, он ее разрешает.

function x() 
{ 
    $levelMappings = @() 
    $levelMappings += @{"a"="b";"c"="d"} 
    $levelMappings += @{"e"="f";"g"="h"} 
    return ,$levelMappings 
} 
(x).gettype().name 
(x) | ConvertTo-Json 

он возвращает

[
{
"с": "д",
"а": "б"
},
{
"г" : "h",
"e": "f"
}
]

Его не идеальный ... но он действительно работает.


Третье обновление, нет, это не сработает. Если его 1-элементный массив из Я вернулся к исходной задаче:

function x() 
{ 
    $levelMappings = @() 
    $levelMappings += @{"a"="b"} 
    return ,$levelMappings 
} 
(x).gettype().name 
(x) | ConvertTo-Json 

дает:

{
"а": "б"
}

Я сдаюсь!!!


Четвертое обновление ...

Ох, и если я швырнуть возвращаемое значение в хэш-таблицу и конвертировать, что JSON:

function x() 
{ 
    $levelMappings = @() 
    $levelMappings += @{"a"="b"} 
    return ,$levelMappings 
} 
$hashtable = @{} 
$hashtable.Add('somekey',(x)) 
$hashtable | ConvertTo-Json 

он выступает в качестве одного элемента массива JSON!

{
"somekey": [
{
"а": "б"
}
]
}

Arrghh !!! :)

+0

'возвращение, $ levelMappings' –

+1

Возможный дубликат [Есть ли способ для вызывающего пользователя получить вывод функции powershell w не подвергая его (возможному) разворачиванию трубопровода?] (http://stackoverflow.com/questions/28724537/is-there-a-way-for-a-caller-to-get-the-output-of-a- powershell-function-without-s) –

+0

О, это красиво. Большое спасибо. Я подумал, что, возможно, это был обман, но он много искал и ничего не нашел. – jamiet

ответ

2

Попробуйте это:

function x() 
{ 
    $levelMappings = @() 
    $levelMappings += @{"a"="b";"c"="d"} 
    return ,$levelMappings 
} 
(x).gettype().name 

Унарный оператор запятой используется для указания PowerShell, чтобы обернуть объект следующего за ним, который сделает объект массив, а не Хеш при возвращении.

+0

Хе-хе, ты избил меня до этого, и с лучшим ответным ответом. – GodEater

+0

спасибо. Я очень благодарен. – jamiet

+0

Он не «делает его массивом» настолько, насколько он обертывает массив в * другом * массиве, так что powershell разворачивает * этот * массив вместо вашего. В основном вы создаете отбрасывающий массив для powershell, чтобы калечить вместо вашего * реального * массива. –

1

Powershell действительно любит разворачивать массивы везде, где может.

Вы можете заставить то, что вы хотите, изменив линию возврата к этому:

return , $levelmappings 

И это будет выскочить как массив.

0

окончательный ответ, который не вызывает ConvertTo-Json возиться с результатом

function x() 
{ 
    $levelMappings = @() 
    $levelMappings += @{"a"="b";"c"="d"} 
    $levelMappings += @{"e"="f";"g"="h"} 
    return ,$levelMappings 
} 
(x).gettype().name 
(x) | ConvertTo-Json 
+0

Только что понял, что не работает, если массив имеет только один элемент, потому что PowerShell снова распакует его! Вздох! Так что я вернулся туда, где начал! Я сдаюсь :) – jamiet

+0

рассмотрите возможность реорганизации кода, чтобы не использовать конвейер, и, возможно, ваша проблема может быть решена, и вы получите улучшенный шаблон для других мест вашего кода. –

0

Иногда трубопровод является вашим другом, а иногда нужно просто разбить код на части и быть преднамеренным, которые могли бы также помогать с читабельностью по дороге или когда другие читают ваш код.

Я искал на «Powershell ConvertTo-JSon сила JSon массив» и первый удар был: ConvertTo-JSON an array with a single item, и Ansgar Wiechers разместил элегантный ответ там, так что, возможно, это дубликат этого. Я полагаю, что это зависит от того, действительно ли этот вопрос «принудительно возвращает функцию для возврата массива» (вопрос) или действительно ли это «заставить ConvertTo-Json всегда создавать массив» (проблема).

Во всяком случае, я считаю, что следующий выполняет все О.П. желания сделать, чтобы:

Код:

function x1() 
{ 
    $levelMappings = @() 
    $levelMappings += @{"a"="b"} 
    return $levelMappings 
} 
"X1: " + (x1).gettype().name 
ConvertTo-Json @(x1) 

function x2() 
{ 
    $levelMappings = @() 
    $levelMappings += @{"a"="b";"c"="d"} 
    return $levelMappings 
} 
"X2: " + (x1).gettype().name 
ConvertTo-Json @(x2) 

function x3() 
{ 
    $levelMappings = @() 
    $levelMappings += @{"a"="b";"c"="d"} 
    $levelMappings += @{"e"="f";"g"="h"} 
    return $levelMappings 
} 
"X3: " + (x1).gettype().name 
ConvertTo-Json @(x3) 

Выход:

X1: Hashtable 
[ 
    { 
     "a": "b" 
    } 
] 
X2: Hashtable 
[ 
    { 
     "c": "d", 
     "a": "b" 
    } 
] 
X3: Hashtable 
[ 
    { 
     "c": "d", 
     "a": "b" 
    }, 
    { 
     "g": "h", 
     "e": "f" 
    } 
] 
Смежные вопросы