PowerShell Invoke-RestMethod пропускает возвращаемое нулевое значение при навигации по значениям массива. Идеи?

Я вызываю API, который возвращает 3 значения в объекте "tags", который имеет значения для "tags.name" и tags.results ". Возвращаются значения, указанные ниже. Но когда я пытаюсь перемещаться по значениям, я можно увидеть, что "нулевое" значение, {}, не было сохранено в массиве. Он просто пропустил его, но мне нужно это значение, поскольку оно полностью разрушает массив.

Есть идеи, как правильно заполнить массив, чтобы он не пропустил это значение {}?

Response Values

values                      attributes                     
------                      ----------                     
{1605560351000 78.129448 3} @{machine_type=System.Object[]}
{}                                                         
{1605560354000 0 3}         @{machine_type=System.Object[]}

Resulting Array
0 : 1605560351000 78.129448 3
1 : 1605560354000 0 3
2 : 

Код nvoke и массива PowerShell:

    $response = Invoke-RestMethod 'https://api' -Method 'POST' -Headers $headers -Body $body

    "Response Values"
    $response.tags.results
    ""
    "Resulting Array"
    "0 : " + $response.tags.results.values[0]
    "1 : " + $response.tags.results.values[1]
    "2 : " + $response.tags.results.values[2]

Возвращенный JSON из Invoke-RestAPI. Вы можете увидеть, где возвращенное значение для второго узла является нулевым.

{
    "tags": [
        {
            "name": "StateComp1",
            "results": [
                {
                    "values": [
                        [
                            1605561152000,
                            75.436455,
                            3
                        ]
                    ],
                }
            ],
        },
        {
            "name": "StateComp2",
            "results": [
                {
                    "values": [],
                }
            ],
        },
        {
            "name": "StateComp3",
            "results": [
                {
                    "values": [
                        [
                            1605561469000,
                            0,
                            3
                        ]
                    ],
                }
            ],
        }
    ]
}

1 ответ

Решение

Проблема не связана с Invoke-RestMethod и вместо того, чтобы объяснить поведение PowerShell в элемент перечисления функции:

Когда вы получаете доступ $response.tags.results.values, то .values свойства на - несколько - .resultsсвойства (вы используете вложенное перечисление членов) эффективно перечисляются следующим образом:

       $response.tags.results | ForEach-Object { $_.values }

При этом пустые массивы эффективно удаляются из вывода, и вы получаете только 2 объекта вывода (каждый из которых содержит внутренний массив вложенных в вашем случае); вы можете проверить это, применив (...).Count к команде выше.

Причина в том, что объекты, выводимые блоком скрипта ({ ... }) отправляются в конвейер, который по умолчанию перечисляет объекты, являющиеся коллекциями (массивами).
С вашего 2-го .valuesvalue - пустой массив (полученный из JSON []и поэтому не $null), нечего перечислять и ничего не выводится, что приводит к эффективному удалению.

Обратите внимание, что вышесказанное подразумевает, что коллекции коллекций сглаживаются перечислением членов; например, если значения свойств представляют собой 3 массива из 2 элементов, логика конвейерного перечисления приводит к единственному массиву из 6 элементов, а не к массиву из 3 элементов, каждый из которых содержит массивы из 2 элементов.


Обходной путь является использовать ForEach()массив метод, который не выполняет этой зачистки, если вы нацелены на имущество путем подачи его имя в качестве строки:

       $values = $response.tags.results.ForEach('values')

@"
Resulting Array"
0 : $($values[0])
1 : $($values[1])
2 : $($values[2])
"@

Обратите внимание, что ваш непустой .valuesсвойства фактически являются вложенными массивами; чтобы избавиться от внешнего массива, используйте $values[0][0], $values[1][0], и $values[2][0].

Предостережение: обходной путь эффективен только в том случае, если вы получаете доступ к свойству по строке имени - .ForEach('values'); кажущаяся эквивалентной команда на основе блока сценария,
.ForEach({ $_.values }) снова удаляет пустые массивы, такие как перечисление членов и ForEach-Objectкомандлет; в качестве альтернативы, однако, вы можете обойти это, заключив вывод блока сценария во вспомогательный, временный одноэлементный массив, который сохраняет исходные массивы, используя унарную форму , оператор конструктор массива:
.ForEach({ , $_.values })
Вы также можете использовать ту же технику с - медленнее - ForEach-Object командлет.

Другие вопросы по тегам