Angular2 parsing from JSON to object
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));
},
() => { }
);
}
Ben
I'm a game developer (Unity, BennuGD, Div Game Studio) I'm a professional web developer (Angular) I'm a professional mobile app developer (Xamarin Forms)
Updated on September 19, 2020Comments
-
Ben over 3 years
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 Objectsconsole.log(MyObject.fromJSON(JSON.parse(json_text)))
returns a list of MyObject
-
Ben over 7 yearsThank you. With your modification, it returns a list of
Object
instead of a list ofUser
. Is there a way to fix it? -
Sefa over 7 yearsTry uncommenting second map
.map((res) => {res.result = <User>res.result});
-
Ben over 7 yearsIt returns an empty json
{}
-
Sefa over 7 yearsat which point you get object array? When you subscribe at component or mapping at service?
-
Ben over 7 yearsWhen I subscribe at component
-
Sefa over 7 yearsI think it's because your return type is
Observable<User[]>
but your json is not. Can you create SearchResponse class to wrap it all? Or just map results property of your response. -
Ben over 7 yearsI've tried with SearchResponse class but it still returns an Object instead.
-
Sefa over 7 yearsHave you also updated services return type? I don't have access to my work pc right now so i'm unable to test & give you an clear answer.
-
Ben over 7 yearsYes my service return type is
Observable<SearchResponse>
-
Sefa over 7 yearsIn my test, it returns SearchResponse with no problem. By the way, cast is only compile-time since javascript doesn't support static typing. Are you getting
any
type at compile time? If you can see the type at your ide it means it's working. You'll always get object at runtime. -
Ben over 7 yearsPlease have a look at my EDIT2 part.
-
Ben over 7 yearsMaybe I should create a separate post for the EDIT2 question?
-
Sefa over 7 yearsI couldn't seem to be able to reproduce this problem. I think it's best if you ask a new question because no one is going to read all this comments and find out you have a different problem now.
-
Ben over 7 yearsThank you, I will post a new question. And thank you for your time! (But saddly I cannot accept your reply as answer, I'm sorry about that :-( ).
-
Sefa over 7 yearsNo worries.. :)