$surnamearr = ([string[]] (ConvertFrom-Json $a1).surname) -ne ''
ConvertFrom-Json $a1
converts the JSON array to an array of PowerShell custom objects (type [pscustomobject]
).
(...).surname
extracts the values of all .surname
properties of the objects in the resulting array, using member-access enumeration.
Cast [string[]]
ensures that the result is treated as an array (it wouldn't be, if the array in $a1
happened to contain just one element) and explicitly casts to strings, so that filtering nonempty values via -ne ''
also works for input objects that happen to have no .surname
property.
-ne ''
filters out all empty-string elements from the resulting array (with an array as the LHS, comparison operators such as -ne
act as array filters rather than returning a Boolean value).
The result is that $surnamearr
is an array containing all non-empty .surname
property values.
As for what you tried:
$tobeaddedarr +=$_.$key+","
This statement implicitly creates a new array, distinct from the array reference the caller passed via the $tobeaddedarr
parameter variable - therefore, the caller never sees the change.
You generally cannot pass an array to be appended to in-place, because arrays are immutable with respect to their number of elements.
While you could pass an mutable array-like structure (such as [System.Collections.Generic.List[object]]
instance, which you can append to with its .Add()
method), it is much simpler to build a new array inside the function and output it.
Therefore, you could write your function as:
function get-keyval
{
param ($key)
# Implicitly output the elements of the array output by using this command.
([string[]] (ConvertFrom-Json $key).surname) -ne ''
}
$surnamearr = get-keyval surname
Note:
Outputting an array or a collection in PowerShell by default enumerates it: it sends its elements one by one to the output stream (pipeline).
- While it is possible to output an array as a whole, via the unary form of
,
, the array-construction operator (
, (([string[]] (ConvertFrom-Json $a1).surname) -ne '')
), which improves performance, the problem is that the caller may not expect this behavior, especially not in a pipeline.
If you capture the output in a variable, such as $surnamearr
here, PowerShell automatically collects the individual output objects in an [object[]]
array for you; note, however, that a single output object is returned as-is, i.e. not wrapped in an array.
- You can wrap
@(...)
around the function call to ensure that you always get an array
- Alternatively, type-constrain the receiving variable:
[array] $surnamearr = ...
, which also creates an [object[]]
array, or something like [string[]] $surnamearr = ...
, which creates a strongly typed string array.