Angular2无法映射单个JSON对象?

时间:2017-03-10 10:03:22

标签: javascript json angular typescript

如何映射和使用作为单个对象而不是数组的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格式。那么,与作为对象数组处理相比,尝试将其作为单个对象处理时,我做错了什么?

2 个答案:

答案 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}}