Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular2 parsing from JSON to object

I'm trying to find the best way to cast my json object to Typescript object. I have a http get service which returns a list of user. My current version works, I have added from JSON function to all my model classes to make the mapping works:

export class User {

    constructor(
        public pk: number,
        public username: string,
        public first_name: string,
        public last_name: string,
        public email: string,
        public profile: UserProfile, ) {
    }

    static fromJSON(json: any): User {
        let user = Object.create(User.prototype);
        Object.assign(user, json);
        user.profile = UserProfile.fromJSON(json.profile);
        return user;
    }
}

That works well. But there is something I don't get in the angular 2 doc. On the heroes tutorial, the JSON is automatically casted to object this way:

  getHeroes (): Observable<Hero[]> {
    return this.http.get(this.heroesUrl)
                    .map(this.extractData)
                    .catch(this.handleError);
  }
  private extractData(res: Response) {
    let body = res.json();
    return body.data || { };
  }

I can't get this method to work on my case, I says that body.data is undefined. Does this method really works?

EDIT:

My http service doesn't returns an array of users. It returns a page which contains an array of users in its 'results' property.

{
  "count": 2,
  "next": null,
  "previous": null,
  "results": [
    {
      "pk": 48,
      "first_name": "Jon",
      "last_name": "Does",
      "profile": {
        "pk": 46,
        "gender": "U"
      }
    },
    {
      "pk": 47,
      "first_name": "Pablo",
      "last_name": "Escobar",
      "profile": {
        "pk": 45,
        "gender": "M"
      }
    }
  ]
}

My service code:

 private extractData(res: Response) {
    let body = res.json().results;
    return body || {}; //<--- not wrapped with data
  }

  search(authUser: AuthUser, terms: string): Observable<User[]> {
    let headers = new Headers({
      'Content-Type': 'application/json',
      'X-CSRFToken': this.cookiesService.csrftoken,
      'Authorization': `Token ${authUser.token}`
    });
    let options = new RequestOptions({ headers: headers });
    return this.http.get(environment.server_url + 'user/?search=' + terms, options)
      .map(this.extractData);
    // .map((response: Response) => response.json());
  }

My search component code:

 onSearch(terms: string) {    
    this.searchService.search(this.user, terms).subscribe(
      response => {       
          console.log(response); // Return array of object instead of array of user
      },
      error => {
          console.log(JSON.stringify(error));
      },
      () => { }
    );
 }

EDIT 2:

To make this case easier, I've wrote this simple code:

  test(){
    let json_text=` [
      {
        "id": 1,
        "text": "Jon Doe"
      },
      {
        "id": 1,
        "text": "Pablo Escobar"
      }
    ]`;

    console.log(<MyObject[]>JSON.parse(json_text)); // Array of objects
    console.log(MyObject.fromJSON(JSON.parse(json_text))); // Array of 'MyObject'
  }



export class MyObject{
  id: number;
  text: string;

   static fromJSON(json: any): MyObject {
        let object = Object.create(MyObject.prototype);
        Object.assign(object, json);
        return object;
    }
}
  • console.log(<MyObject[]>JSON.parse(json_text)) returns a list of Objects
  • console.log(MyObject.fromJSON(JSON.parse(json_text))) returns a list of MyObject
like image 743
Ben Avatar asked Oct 16 '16 16:10

Ben


1 Answers

It's because in Angular tutorial, json is in the data property.

As stated in the tutorial

Make no assumptions about the server API. Not all servers return an object with a data property.

If you are not wrapping your json with any property you can just use

private extractData(res: Response) {
  let body = res.json();
  return body || { }; //<--- not wrapped with data
}

Update:

Component code

 onSearch(terms: string) {    
    this.searchService.search(this.user, terms).subscribe(
      (response: SearchResponse) => {    // <--- cast here   
          console.log(response); 
      },
      error => {
          console.log(JSON.stringify(error));
      },
      () => { }
    );
 }
like image 107
Sefa Avatar answered Oct 10 '22 19:10

Sefa