arow arow - 1 month ago 9
Javascript Question

How to cast all nodes of a nested JSON tree to instances of a class in angular 2 Typescript?

I have a class named Leaf, and I'd like to make all nodes of a json response instances of Leaf.
The json response looks like this:

JSON Response

{
"name":"animal",
"state":false,
"children":[
{
"name":"cats",
"state":false,
"children":[
{
"name":"tiger",
"state":false,
},
{
"name":"puma",
"state":false,
"children":[
{
"name":"babyPuma",
"state":true
}
]
}
]
},
{
"name":"dogs",
"state":false,
"children":[
{
"name":"pitbull",
"state":true
},
{
"name":"german",
"state":false,
"children":[
{
"name":"shepherd",
"state":true
}
]
}
]
}
]
}


I am getting the response using observable and have learned to cast the first node:

http.service.ts snippet

getTreeData(): Observable<Leaf>{
var headers = new Headers();
headers.append('Content-Type', 'application/json');
return this.http.post('http://localhost:8000/',{ headers: headers ...})
.map(res =>new Leaf(res.json()));//maybe I could do something here?
}


and here is my Leaf class just in case:

Leaf.ts

export class Leaf{
name: string;
state: string;
treeData: Array<Leaf>;


constructor(input:any){
this.name = input.name;
this.state = input.state;
this.treeData = input.children;
}

toggleState() {
if (this.state=='active'){
this.state = 'inactive';
}
else {
this.state = 'active'
}
}
}


My final goal is to get the json tree and represent them in a folder tree format. Is there a way to use map() to go through all nodes or combination of map() and some sort of traverser?

Answer

I'd first create an interface for the json data:

interface LeafJson {
    name: string;
    state: string;
    children?: LeafJson[];
}

And then use Array.map to create the children:

export class Leaf {
    name: string;
    state: string;
    treeData: Array<Leaf>;

    constructor(input: LeafJson){
        this.name = input.name;
        this.state = input.state;
        this.treeData = input.children ? input.children.map(item => new Leaf(item)) : [];
    }

    toggleState() {
        if (this.state=='active'){
            this.state = 'inactive';
        } else {
            this.state = 'active'
        }
    }
}

(code in playground)