Search code examples
powershellpowershell-6.0

Pass json array to function in powershell


I have this short script which displays a table with row numbers and asks the user which Azure subscription wants to use. It works neatly.

$subscriptions = $(& az account list --query '[].{name:name}' --output json) | ConvertFrom-Json
$subscriptions | ForEach-Object {$index=0} {$_; $index++} | Format-Table -Property @{ Label="index";Expression={$index}; Width=5 },Name
$subChoice = Read-Host 'Choose subscription'

Now I want to write a little function for displaying the table and choosing an item from it, to reuse it for other choices.

function GetChoice {
    param (
        [Parameter(Mandatory = $true)][psobject] $list,
        [Parameter(Mandatory = $true)][string] $prompt
    )    
    $list | ForEach-Object {$index=0} {$_; $index++} | Format-Table -Property @{ Label="index";Expression={$index}; Width=5 },Name
    $choice = Read-Host $prompt
}

When I'm calling it with $subChoice = GetChoice $subscriptions 'Choose subscription' it doesn't display the table.

Why it doesn't work and what should I modify in order to make it work?


Solution

  • Supposing the result of line $subscriptions = $(& az account list --query '[].{name:name}' --output json) | ConvertFrom-Json looks anything like this:

    $subscriptions = [PsCustomObject] @{ 'Name' = 'Subscription one' },
                     [PsCustomObject] @{ 'Name' = 'Subscription two' },
                     [PsCustomObject] @{ 'Name' = 'Subscription three' }
    

    Then change your GetChoice function into:

    function Get-Choice {
        param (
            [Parameter(Mandatory = $true, Position = 0)][psobject[]] $list,
            [Parameter(Mandatory = $true, Position = 1)][string] $prompt
        ) 
        $index = 0
        $msg = $list | ForEach-Object { [PsCustomObject] @{'Index' = $index++; 'Name' = $_.Name }} | Format-Table -AutoSize | Out-String
        Write-Host $msg
        Read-Host $prompt
    }
    

    and call it like this

    $choice = Get-Choice $subscriptions 'Choose subscription'
    # show whatever the user typed in
    $choice
    

    Result:

    Index Name              
    ----- ----              
        0 Subscription one  
        1 Subscription two  
        2 Subscription three
    
    
    
    Choose subscription:
    

    I've changed the function name to comply with the verb-noun naming convention.