Mister Iks
Mister Iks

Reputation: 195

PowerShell update nested value

I have the following output from a PowerShell command and want to update the value for EmployeeID Unfiltered output

I can filter the output with $test.identifiers | where {$_.name -like "EmployeeID" } Filtered output

But if I try to update the value with

$test.identifiers | where {$_.name -like "EmployeeID" } | foreach {$_.values.value = "098324"} 

I get an error Error

How can I update this nested value?

Upvotes: 1

Views: 2296

Answers (2)

mklement0
mklement0

Reputation: 437062

$_.values contains an array (or collection) objects, which explains why you can get (read) the .value property, but not set (write) it (see below).

If you expect the array to have just one element, simply use [0] to access that element directly:

$test.identifiers | where {$_.name -like "EmployeeID" } | foreach {
  $_.values[0].value = '098324'
} 

If there are multiple elements, use
$_.values | foreach { $_.value = '098324' } to assign to them all, or, alternatively in PSv4+,
$_.values.ForEach('value', '098324')


In PSv3+ a feature called member-access enumeration allows you to access a property on a collection and have the property values from the individual elements returned as an array.

However, that only works for getting properties, not for setting them.

When you try to set, only the collection's own properties are considered, which explains the error you saw - an array itself has no .value property.

While this asymmetry is by design, to avoid potentially unwanted bulk modification, the error message could certainly be more helpful.


Simple reproduction of the problem:

Create an object with property one containing a single-element array with another object, with property two:

$obj = [pscustomobject] @{ one = , [pscustomobject] @{ two = 2 } }

The default output looks as follows:

PS> $obj

one
---
{@{two=2}}

The outer {...} indicate an array, as in your case, and what's inside is a hashtable-like notation that PowerShell uses to represent custom objects.

Getting the nested-inside-an-array object's two property works as intended:

PS> $obj.two
2

Trying to set it fails:

PS> $obj.two = 2.1
The property 'two' cannot be found on this object. Verify that the property exists and can be set.

To set, use .ForEach(), for instance:

PS> $obj.ForEach('two', 2.1); $obj

one
---
{@{two=2.1}}

Upvotes: 3

NickB
NickB

Reputation: 7

Have you tried it this way with the full object path:

$test.identifiers | where {$_.name -like "EmployeeID" } | foreach {$_.identifiers.values.value = "098324"}

Upvotes: 0

Related Questions