1

I'm processing through Powershell script some API result processing. API data (json) come from this :

$tree = Invoke-WebRequest -Uri "xxxxxxxxmonURLxxxxxxxxxx/130333"  
$children = ($tree.Content | ConvertFrom-Json).data.12345.children

Then I loop through $children object using | ForEach $_ within loop has "147852" as $_.Name, and the following object as $_.Definition I'd like to parse the object within $_.Definition but cannot figure out how to access it.

The Definition object looks like this:

  TypeName : System.Management.Automation.PSCustomObject
 
Name   MemberType   Definition
----   ----------   ----------
147852 NoteProperty System.Management.Automation.PSCustomObject 147852=@{nodeType=node; name=test1; flag=N0; creationDate=2022-02-17T14:50:16+00:00; hasAlerts=False; children=}

And I wish to access any property within the 147852 key (such as nodeType, name, flag, ..., children).

$_.147852 outputs an error saying 147852 was not found.

Thanks.

API json returned:

{
    "data": {
        "130333": {
            "nodeType": "node",
            "name": "Test name",
            "flag": "N0",
            "children": {
                "147852": {
                    "nodeType": "node",
                    "name": "test1",
                    "flag": "N0",
                    "hasAlerts": false,
                    "children": {
                        "147853": {
                            "nodeType": "node",
                            "name": "test2",
                            "flag": "N0",
                            "children": {
                                "NP12-N9-S4": {
                                    "nodeType": "agent",
                                    "name": "Win10",
                                    "type": "S"
                                }
                            }
                        }
                }
            }
        }
    }
} 
Potemkin
  • 76
  • 9
  • 1
    Please, add your JSON as plain text to your question – Santiago Squarzon Feb 21 '22 at 19:52
  • 4
    What about `$_.'147852'`? – Jeroen Mostert Feb 21 '22 at 19:53
  • @SantiagoSquarzon Edited 1st post :) – Potemkin Feb 21 '22 at 20:02
  • @JeroenMostert $_."147852" as well as $_.Definition."147852" doesn't output anything :'( – Potemkin Feb 21 '22 at 20:05
  • 2
    `$json.data.'130333'.children.'147852'` should work just fine as Jeroen Mostert stated before – Santiago Squarzon Feb 21 '22 at 20:07
  • 2
    Well yeah, there's no `Definition` in your JSON anywhere... `Definition` is part of the metadata of the property, not your actual data. `.data.'130333'.children.'147852'` works fine on my end. – Jeroen Mostert Feb 21 '22 at 20:08
  • In JSON put as sample, "children" key below the "Test name" is the one I' could manage putting in $children variable then loop through it. 147852 is one key among several that I'm trying to access (to get, for example the child value "test2" as "name" key. – Potemkin Feb 21 '22 at 20:08
  • 1
    Does this answer your question? [Why can't I dot-reference a hashtable key's value property if the property name is an integer](https://stackoverflow.com/questions/68762971/why-cant-i-dot-reference-a-hashtable-keys-value-property-if-the-property-name) – codewario Feb 21 '22 at 20:10
  • 1
    Note that dot-referencing is flexible enough to handle variables as well, and by extension expressions. `$json.data.(($json.data | Get-Member -Type NoteProperty)[0].Name)` will give you the first property, no matter its name. Looping can be done similarly. – Jeroen Mostert Feb 21 '22 at 20:13
  • 2
    Omg I'm so stupid. I was looping using `$children | Get-Member -type NoteProperty | ForEach-Object` Thanks to your post @JeroenMostert talking about metadata, I understood there was maybe a mistake in it. Changing to `$children | ForEach-Object` made it work as expected. Thanks to all of you <3 – Potemkin Feb 21 '22 at 20:13
  • 3
    There is no such thing as stupid when there is learning :) – Santiago Squarzon Feb 21 '22 at 20:15

1 Answers1

2

Jeroen Mostert provided the crucial pointer in the comments, and Bender the Greatest links to what is effectively a duplicate question, but given that the latter is hashtable-focused, let me recapitulate the problem in the context of custom objects ([pscustomobject]):

Leaving the accidental use of Get-Member out of the picture, your problem ultimately boils down to a parser bug in PowerShell (see GitHub issue #14036):

To avoid it, quote property names that look like numbers - e.g., to access property 147852 on object $obj, use $obj.'147852'

Strictly speaking, the bug only surfaces if you attempt an additional (nested) property access:

# Nested sample custom object.
$obj = [pscustomobject] @{ 147852 = [pscustomobject] @{ name = 'test1' } }

# OK - number-like property is accessed without quoting, but *not nested*.
# However, $obj.'147852' is preferable.
$obj.147852

# *Nested* property access:

# !! BUG triggers error: "Missing property name after reference operator."
$obj.147852.name

# OK: Quoting avoids the problem.
$obj.'147852'.name # -> 'test1'
mklement0
  • 382,024
  • 64
  • 607
  • 775
  • 2
    It's a good thing we have you to dig down to the nitty-gritty of these things. My approach to solving the bug would have been to disallow things like `$obj.147852` entirely, because *of course* that's not an identifier and *of course* you have to quote it (if you don't want to use expression syntax a la `$obj.(147852)`). But apparently the intent is to make this work, and it's the failed nesting that is the actual bug. Whoops, good thing I didn't break all of that code. :P – Jeroen Mostert Feb 21 '22 at 21:57
  • @JeroenMostert :) The problem is that PowerShell is more permissive than C#, for instance, both with respect to `[pscustomobject]` instances and `class` definitions, e.g. `class Foo { [string] $123 = 'one two three' }`. For that reason, allowing `.123` makes sense. What does _not_ make sense, however, is to interpret `.123.` _as a single property name that is a `[double]`_, which is the source of the bug. – mklement0 Feb 21 '22 at 22:28
  • P.S., @JeroenMostert: since PowerShell also allows property-access syntax with _dictionaries_ (hashtables / types that implement `IDictionary`), whose _keys_ can be of _any type_ - unlike object _properties_, which are invariably _strings_ - there is _some_ justification for interpreting `123.` as a `[double]` - but to me that isn't convincing, given that binary-to-decimal rounding errors inherently make `[double]` instances unsuitable as _keys_. – mklement0 Feb 21 '22 at 22:50