简体   繁体   中英

powershell psobject nested with same reference. from json

I'm having difficulty accessing the nested part of a psobject. I've used

$response = Invoke-RestMethod

to pull back information from an application. $response then contains a json file.

I've santized the json file but this is the general format.

Response:{
    "total":  2,
    "items":  [
                  {
                      "id":  1,
                      "name":  "127.0.0.1",
                      "properties":  [
                                               {
                                                   "name":  "var1",
                                                   "value":  "10"
                                               },
                                               {
                                                   "name":  "var2",
                                                   "value":  "20"
                                               },
                                               {
                                                   "name":  "var3",
                                                   "value":  "30"
                                               },
                                               {
                                                   "name":  "var4",
                                                   "value":  "40"
                                               }
                                            ]
                  },
                  {
                      "id":  2,
                      "name":  "10.2.2.2",
                      "properties":  [
                                               {
                                                   "name":  "var1",
                                                   "value":  "100"
                                               },
                                               {
                                                   "name":  "var2",
                                                   "value":  "200"
                                               },
                                               {
                                                   "name":  "var3",
                                                   "value":  "300"
                                               },
                                               {
                                                   "name":  "var4",
                                                   "value":  "400"
                                               },
                                               {
                                                   "name":  "var5",
                                                   "value":  "500"
                                               }
                                            ]
                  },
              ],
    "searchId":  null,
    "isMin":  false
}

I can easily access the id and name directly under the items layer using a simple for loop

for ( $index = 0; $index -lt $data.Items.count; $index++)
{
    $id=$data.Items.id[$index]
    $name=$data.Items.name[$index]
}

but i can't find out how to reference the stuff under the properties section.

This is some of the stuff i've tried

    $var1 = Select-Object -ExpandProperty  $data.Items.properties[$index] 
    $var1 = $data.Items.properties[$index] | Select-Object -expand name
    $var1 = $data.Items.properties[$index] | Select -property *

Some of it gets close, but only returns one of the name entries and not all.

It is important where you apply the index. Applying the index at the very end of your expression works in some cases, but not quite in the way, that you might expect. Lets have a closer look at what you are exactly doing:

$id = $data.Items.id[0]

$data.Items.id returns an array of all ids of all "Items" elements:

PS> $data.Items.id

1
2

With $data.Items.id[0] you address the first element of that array, which is the value that you want.

Now compare that to the following:

$id = $data.Items[0].id

$data.Items returns an array of all "Items" elements:

PS> $data.Items

id name      properties
-- ----      ----------
 1 127.0.0.1 {@{name=var1; value=10}, @{name=var2; value=20}, @{name=var3; value=30}, @{name=var4; value=40}}
 2 10.2.2.2  {@{name=var1; value=100}, @{name=var2; value=200}, @{name=var3; value=300}, @{name=var4; value=400....}

With $data.Items[0] you address the the first element of the array:

PS> $data.Items[0]

id name      properties
-- ----      ----------
 1 127.0.0.1 {@{name=var1; value=10}, @{name=var2; value=20}, @{name=var3; value=30}, @{name=var4; value=40}}

And with $data.Items[0].id you address the the first element of the array and select only the content of it`s id-property.

The benefit of addressing a single object first before expanding its properties will be clear once you have properties, that contain more than a single value. Compare the following output:

PS> $data.Items.properties[0]

name value
---- -----
var1 10
PS> $data.Items[0].properties

name value
---- -----
var1 10
var2 20
var3 30
var4 40

As you said in the comments, you would further want to change the value of one particular property. I suggest you narrow the properties down by using Where-Object :

PS> $var2 = $data.Items[0].properties | Where-Object Name -eq 'var2'
PS> $var2.value = 25
PS> $data.Items[0].properties

name value
---- -----
var1 10
var2 25   <---
var3 30
var4 40 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM