如何映射和使用作为单个对象而不是数组的JSON响应?
最近,我开始在我正在处理的项目中添加一项新功能,该项目应该从API获取JSON响应并填写包含数据的简单模板。难道不难,对吧?嗯,不......但是,是的......
模拟JSON响应的版本:
{
"id": 1,
"name": "Acaeris",
}
profile.service.ts
import { Injectable } from '@angular/core';
import { Http, Response } from '@angular/http';
import { Observable } from 'rxjs/Observable';
import { Profile } from './profile';
/**
* This class provides the Profile service with methods to read profile data
*/
@Injectable()
export class ProfileService {
/**
* Creates a new ProfileService with the injected Http.
* @param {Http} http - The injected Http.
* @constructor
*/
constructor(private http: Http) {}
/**
* Returns an Observable for the HTTP GET request for the JSON resource.
* @return {Profile} The Observable for the HTTP request.
*/
get(): Observable<Profile> {
return this.http.get('assets/profile.json')
.map(res => <Profile>res.json())
.catch(this.handleError);
}
/**
* Handle HTTP error
*/
private handleError (error: any) {
let errMsg = (error.message) ? error.message :
error.status ? `${error.status} - ${error.statusText}` : 'Server error';
console.error(errMsg);
return Observable.throw(errMsg);
}
}
profile.component.ts
import { Component, OnInit } from '@angular/core';
import { ProfileService } from '../services/profile/profile.service';
import { Profile } from '../services/profile/profile';
/**
* This class represents the lazy loaded ProfileComponent
*/
@Component({
moduleId: module.id,
selector: 'sd-profile',
templateUrl: 'profile.component.html',
styleUrls: ['profile.component.css'],
})
export class ProfileComponent implements OnInit {
errorMessage: string;
profile: Profile;
/**
* Creates an instance of the ProfileComponent with the injected
* ProfileService
*
* @param {ProfileService} profileService - The injected ProfileService
*/
constructor(public profileService: ProfileService) {}
/**
* Get the profile data
*/
ngOnInit() {
this.getProfile();
}
/**
* Handles the profileService observable
*/
getProfile() {
this.profileService.get()
.subscribe(
data => this.profile = data,
error => this.errorMessage = <any>error
);
}
}
profile.ts
export interface Profile {
id: number;
name: string;
}
我只是尝试使用{{profile.name}}
输出它,但这最终会导致控制台显示一大堆错误消息而没有输出。如果我在加载后检查profile
的内容,则会告诉我它是undefined
。
然而,这是一个令人困惑的部分。如果我将所有Profile
引用替换为Profile[]
,将JSON包装在一个数组中,添加*ngFor="let p of profile"
abd使用{{p.name}}
一切正常。不幸的是,在实际完成的应用程序中,我无法控制JSON格式。那么,与作为对象数组处理相比,尝试将其作为单个对象处理时,我做错了什么?
答案 0 :(得分:6)
看起来表达式{{profile.name}}在页面呈现时未定义配置文件变量。您可以尝试添加一些这样的getter:
get profileName(): string { return this.profile ? this.profile.name ? ''; }
并在模板{{profileName}}中使用,或者您可以在模板中使用ngIf,如下所示:
<div *ngIf="profile">{{profile.name}}</div>
或更短(如下面评论中提到的drewmoore):
<div>{{profile?.name}}</div>
当您使用数组时,情况也是如此 - 首先渲染时数数组是未定义的。 ngFor为您处理此问题并且不提供任何内容。获取“个人资料项目”的异步操作完成后,再次使用正确的值重新呈现UI。
答案 1 :(得分:-1)
map
函数返回Observables,它是元素的集合。它基本上与数组的map
函数的工作方式相同。
现在要解决,您可以Profile
替换Profile[]
引用,并使用{{profile[0].name}}
。