Programatically gathering nested object keys from response in Angular

Viewed 44

I am receiving a nested response back from a server in my Angular app. I need to access the data inside, but there are several responses contained within one parent object. So far I have been able to drill inside somewhat, but I am having trouble getting in further.

So far I have this code:

getPlants(): Observable<any> { 
const headers = { headers: this.headers };
return this.httpClient.get(`${this.requestUrl}, headers);
}

This gets the data in question. Next, I have the function where I am having issues.

destructurePlants() {

         this.getPlants().subscribe(data => {
         const plants = Object.keys(data).map(e => data[e]);
         plants.forEach(plant => {
              console.log(plant);
         });
    }

The data I am getting back comes back like this.

{
     "plantMap": {
          "1": {
               "PLANTTYPE1": {
                    "id": "1",
                    "style": "plantStyle",
                    "styleDesc": "Luxurious green",
                    "codeId": "1"
               },
               "PLANTTYPE2": {
                    "id": "1",
                    "style": "plantStyle2",
                    "styleDesc": "Luxurious red",
                    "codeId": "2"
               },
               "PLANTTYPE3": {
                    "id": "1",
                    "style": "plantStyle3",
                    "styleDesc": "Luxurious succulent",
                    "codeId": "3"
               },
          "2": {
               "TREE1": {
                    "id": "2",
                    "style":"plantStyle",
                    "styleDesc":"Oak",
                    "codeId": "1"
               },
               "TREE2": {
                    "id": "2",
                    "style": "plantStyle2",
                    "styleDesc": "Evergreen",
                    "codeId": "2"
               },
               "TREE3": {
                    "id": "2",
                    "style": "plantStyle3",
                    "styleDesc": "Myrtle",
                    "codeId": "3"
               }
         }
     }
} 

Ideally, I would like to be able to grab each 1, 2, etc and then drill down further into PLANTTYPE AND TREETYPE objects, etc.

2 Answers

you forgot one closing } for your plantMap["1"], beside that, The output of the snippet below is array of plants.

"1": {
           "PLANTTYPE1": {
                "id": "1",
                "style": "plantStyle",
                "styleDesc": "Luxurious green",
                "codeId": "1"
           },
           "PLANTTYPE2": {
                "id": "1",
                "style": "plantStyle2",
                "styleDesc": "Luxurious red",
                "codeId": "2"
           },
           "PLANTTYPE3": {
                "id": "1",
                "style": "plantStyle3",
                "styleDesc": "Luxurious succulent",
                "codeId": "3"
           },
      "2": {

const data =  {
          "1": {
               "PLANTTYPE1": {
                    "id": "1",
                    "style": "plantStyle",
                    "styleDesc": "Luxurious green",
                    "codeId": "1"
               },
               "PLANTTYPE2": {
                    "id": "1",
                    "style": "plantStyle2",
                    "styleDesc": "Luxurious red",
                    "codeId": "2"
               },
               "PLANTTYPE3": {
                    "id": "1",
                    "style": "plantStyle3",
                    "styleDesc": "Luxurious succulent",
                    "codeId": "3"
               }},
          "2": {
               "TREE1": {
                    "id": "2",
                    "style":"plantStyle",
                    "styleDesc":"Oak",
                    "codeId": "1"
               },
               "TREE2": {
                    "id": "2",
                    "style": "plantStyle2",
                    "styleDesc": "Evergreen",
                    "codeId": "2"
               },
               "TREE3": {
                    "id": "2",
                    "style": "plantStyle3",
                    "styleDesc": "Myrtle",
                    "codeId": "3"
               }
         }
     };
      
let arr = [];
const plants = Object.keys(data).map(e => data[e]);
plants.forEach(plant => {
  const plant_ = Object.keys(plant).map(e => plant[e]);
  arr.push(...plant_);
});
console.log(arr);

You can (recommanded) use rxjs to access your data. The way you do it highly depend on what you want to achieve but here is a simple example on Stackblitz of how you can do that, and here is the code :

import { of } from 'rxjs'; 
import { map, pluck, tap } from 'rxjs/operators';


const data = {
     "plantMap": {
          "1": {
               "PLANTTYPE1": {
                    "id": "1",
                    "style": "plantStyle",
                    "styleDesc": "Luxurious green",
                    "codeId": "1"
               },
               "PLANTTYPE2": {
                    "id": "1",
                    "style": "plantStyle2",
                    "styleDesc": "Luxurious red",
                    "codeId": "2"
               },
               "PLANTTYPE3": {
                    "id": "1",
                    "style": "plantStyle3",
                    "styleDesc": "Luxurious succulent",
                    "codeId": "3"
               },
          },
          "2": {
               "TREE1": {
                    "id": "2",
                    "style":"plantStyle",
                    "styleDesc":"Oak",
                    "codeId": "1"
               },
               "TREE2": {
                    "id": "2",
                    "style": "plantStyle2",
                    "styleDesc": "Evergreen",
                    "codeId": "2"
               },
               "TREE3": {
                    "id": "2",
                    "style": "plantStyle3",
                    "styleDesc": "Myrtle",
                    "codeId": "3"
               }
          }
      }
};

const data$ = of(data);
let plantTypes;
let trees;

data$.pipe(
  pluck('plantMap'),
  tap(obj => {
    plantTypes = obj['1'];
    trees = obj['2'];
  }),
  tap(_ => {
    console.log('plantTypes = ', plantTypes);
    console.log('trees = ', trees);
  })
).subscribe();

Here I use pluck to select the node I want to target. Pretty simple here since you have only one.

Then I set both segments of data inside constant with tap and then display them with another tap (could be in the same of course, just an example to show that you can chain method inside the pipe).

The last subscribe() is just here to trigger the code. It is only triggered when a subscription is made to the observable, either like that of though the asyncPipe of angular (which is a must use when you can).

If you want to access you data differently, please explain your context and what you try to achieve and i'll edit my answer :).

Note that I added a bracket { to close the 1 part of your object, I assumed it should be like this.

Related