8

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

2 Answers 2

3

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));
      },
      () => { }
    );
 }
Sign up to request clarification or add additional context in comments.

15 Comments

Thank you. With your modification, it returns a list of Object instead of a list of User. Is there a way to fix it?
Try uncommenting second map .map((res) => {res.result = <User>res.result});
It returns an empty json {}
at which point you get object array? When you subscribe at component or mapping at service?
When I subscribe at component
|
0

I am quite late to this topic but found my self into the same issue . I am learning Angular and want to convert JSON received from HTTP server to my model object .

Service Class

var ele:User;
let k=this.http.get<User>(url).subscribe(data => {
                                            ele=data;
                                            console.log(ele.count);
                                            console.log(ele.results[0].first_name);
                                            console.log(ele.results[0].profile.gender);
                                            } 
                                         );

My Model for holding the information of JSON

export interface User{
    count: string;
    next: string;
    previous: string;
    results: Result[];
}
export interface Result{
    pk: string;
    first_name: string;
    last_name: string;
    profile:Profile;
}
export interface Profile{
    pk: string;
    gender:string;
}

And this is it. I am using Angular 6 for parsing JSON to Object

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.