1

In Powershell, how do I reduce an array of JSON objects, like this below, into a simple String array of "Name"? I am NOT encountering this issue with a normal Json-Object (non-array).

[
    {
        "Name":"Name1",
        "Id": 3433
    },
    {
        "Name":"Name2",
        "Id": 5455
    }
]

Into this:

[
    "Name1", 
    "Name2"
]

Here is what I am trying to do. This code does NOT return an array; instead, it returns the value of the first item in the array.

function FindServiceBusNamespaces($ResourceGroup) {
    $toExecute = "az servicebus namespace list --resource-group ${ResourceGroup}"
    $response = GetAzResponseObject -Expression "$toExecute"
    $namespaceArray = @()
    foreach ($ns in $response)
    {
        $namespaceArray += $ns | Select-Object -ExpandProperty id
    }
    return $namespaceArray
}

And same result with this:

function FindServiceBusNamespaces($ResourceGroup) {
    $toExecute = "az servicebus namespace list --resource-group ${ResourceGroup}"
    $response = GetAzResponseObject -Expression "$toExecute"
    $namespaceArray = @()
    foreach ($ns in $response)
    {
        $namespaceArray += $ns.id
    }
    return $namespaceArray
}
djangofan
  • 28,471
  • 61
  • 196
  • 289

1 Answers1

1

Without knowing what GetAzResponseObject returns, it's hard to diagnose your problem, but to answer the question at the start of your post:

$jsonArr = @'
[
    {
        "Name":"Name1",
        "Id": 3433
    },
    {
        "Name":"Name2",
        "Id": 5455
    }
]
'@

$res = (ConvertFrom-Json $jsonArr).Name

ConvertTo-Json @($res)

yields:

[
  "Name1",
  "Name2"
]

Note:

  • @(...), the array-subexpression operator around $res ensures that the value serializes as a JSON array, even if $res happens to contain only one .Name value.

  • This is necessary, because in the PowerShell pipeline, which enumerates arrays (enumerables in general), a single-element input array effectively turns into its one and only element, i.e. the array wrapper is lost. This behavior also applies to member-access enumeration, because (...).Name is in essence the same as ... | ForEach-Object { $_.Name }

mklement0
  • 382,024
  • 64
  • 607
  • 775
  • Thanks! You gave me the hint I needed to solve it. – djangofan Jul 27 '22 at 15:41
  • Glad to hear it, @djangofan, but please consult with me before making substantial edits to my answer. Please see my update, which - given that you wanted split the single pipeline into multiple steps - uses [member-access enumeration](https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_Member-Access_Enumeration) to extract the `.Name` property values. Also, there's no good reason to use `Write-Host` here, [which is often the wrong tool to use](https://stackoverflow.com/a/60534138/45375). – mklement0 Jul 27 '22 at 23:15
  • 1
    @djangofan, I've also added a hint re use of `@(...)`, as I'm now seeing that your original problem may have been about a JSON input array with only a _single_ element turning into _just that element_ in the pipeline, i.e. the array wrapper getting lost. – mklement0 Jul 28 '22 at 01:17
  • 1
    yep, thanks. a wierdness when array comes back with single value – djangofan Aug 03 '22 at 20:27
  • @djangofan, yes, it's a classic PowerShell pitfall. [This answer](https://stackoverflow.com/a/60020105/45375) has information about the design rationale behind it. – mklement0 Aug 03 '22 at 20:30