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 MyObjectIt'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));
},
() => { }
);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With