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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.