'Select-Object Data Failure From Succesful Invoke-RestMethod
I have a working call to a rest service using Invoke-RestMethod -Uri https://.... The call's result, in JSON, can be piped the data to Format-Table -Property ... and data is shown.
But when Select-Object -Property ... is used after the invoke with the same parameters, the PSObject has the columns but no data for them. If I use a different webservice the call will work.
What could be causing the PSObject to not show any values?
Working Example on public rest web services
Invoke-RestMethod -Uri https://jsonplaceholder.typicode.com/todos/1 |
Select-Object -Property title
Result
@{title=delectus aut autem}
New Failure Different API
Invoke-RestMethod -Uri https://cat-fact.herokuapp.com/facts | Select-Object -Property text
Solution 1:[1]
You've stumbled upon an unholy combination of two PowerShell oddities when converting JSON arrays:
Invoke-RestMethodandConvertFrom-Jsonsend converted-from-JSON arrays as a whole through the pipeline, instead of element by element, as usual:Note: In PowerShell (Core) 7.0,
ComvertFrom-Json's behavior was changed to align with the usual enumeration-of-elements behavior, and a-NoEnumerateswitch was added as an opt-in to the old behavior. For the discussion that led to this change, see GitHub issue #3424.However, as of this writing (PowerShell (Core 7.2)
Invoke-RestMethodstill exhibits this unexpected behavior, which is discussed in GitHub issue #15272.
Select-Objectdoes not perform member-access enumeration, so it looks for the specified property (e.g.,text) directly on the array, where it doesn't exist.
To demonstrate the problem with a simple example:
# Windows PowerShell only:
# Because ConvertFrom-Json sends an *array* (of 2 custom objects) through
# the pipeline, Select-Object looks for property .text on the *array* -
# and can't find it.
# The same applies to Invoke-RestMethod (also still in
# PowerShell (Core) as of v7.2)
PS> ConvertFrom-Json '[{ "text": "a" }, { "text": "b" }]' | Select-Object text
text
----
# NO VALUES
A simple workaround is to enclose the ConvertFrom-Json / Invoke-RestMethod call in (...), which forces enumeration of the array, causing Select-Object to work as expected.:
# (...) forces enumeration
PS> (ConvertFrom-Json '[{ "text": "a" }, { "text": "b" }]') | Select-Object text
text
----
a
b
Note that a command such as Select-Object -Property text (without -ExpandProperty) still output custom objects that have a .text property, not the .text property values.
If all you're interested in is property values, the solution is simpler, because you can use the above-mentioned member-access enumeration directly on the array:
# Using .<propName> on an array (collection) implicitly returns the
# property values from the *elements* of that collection (member-access enumeration).
PS> (ConvertFrom-Json '[{ "text": "a" }, { "text": "b" }]').text
a
b
Note how the output now has no text header, because it is mere string values that are being output, not custom objects.
Solution 2:[2]
your problem in the 2nd example is that there is NO prop named text. [grin]
the only prop is all and that contains an array of objects that DO contain a prop named text. so you need something that can get that deeper prop. one way is to use two Select-Object calls. something like this ...
$Url = 'https://cat-fact.herokuapp.com/facts'
$RawIRM = Invoke-RestMethod -Uri $Url
$SO_IRM = $RawIRM |
Select-Object -ExpandProperty all |
Select-Object -Property text
the $SO_IRM var now has an array of 178 strings about cats. [grin]
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | |
| Solution 2 | Lee_Dailey |


