如何在获取方法后将json对象数组解析为打字稿(对象)

时间:2018-09-04 00:10:30

标签: json angular typescript

我是angular的初学者,并开始构建我的第一个应用程序。我的目标是构建将要从其他服务继承的通用服务。我正在跟踪方法Generic HTTP Service的链接结构。在读取方法中,我使用Serializer类将响应json对象转换为我的打字稿,并且可以正常工作。我收到地图错误。我该怎么解决?

服务代码:

import { Injectable } from '@angular/core';
import { Http, Headers } from '@angular/http';
import 'rxjs/add/operator/map';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Resource } from '../models/resource.model';
import { Observable } from 'rxjs/Observable';
import { Serializer } from '../serializer/serializer';
import { AuthenticationService } from './authentication.service';

@Injectable()
export class SharedService<T extends Resource> {

  constructor(
    private httpClient: HttpClient,
    private url: string,
    private endpoint: string,
    private authentication: AuthenticationService,
    private serializer: Serializer
  ) { }


  create(resource: T) {
    let headers = new HttpHeaders();
    headers = headers.set('Content-Type', 'application/json; charset=utf-8');
    return this.httpClient.post(`${this.url}/${this.endpoint}`, JSON.stringify(resource), { headers: headers });
  }



  //PUT
  update(item: T): Observable<T> {
    return this.httpClient.put<T>(`${this.url}/${this.endpoint}`, JSON.stringify(item), { headers: this.addHeaders() })
      .map(data => this.serializer.fromJson(data) as T);
  }



  //GET
  read(id: number): Observable<T> {
    return this.httpClient.get(`${this.url}/${this.endpoint}/${id}`, { headers: this.addHeaders() })
      .map((data: any) => this.serializer.fromJson(data) as T);
  }

  //GET ALL
  list(): Observable<T[]> {
    return this.httpClient.get<T>(`${this.url}/${this.endpoint}` , {headers : this.addHeaders()})
      .map((data: any) =>
        this.convertData(data.items));
  }

  protected convertData(data: any): T[] {

    return data.map(item => {this.serializer.fromJson(item)});
  }

  protected addHeaders() {
    let token = ('Bearer ' + this.authentication.getToken()).valueOf();
    let headers = new HttpHeaders();
    headers = headers.set('Content-Type', 'application/json; charset=utf-8').set('Authorization', token);
    return headers;
  }

}

UserService:

import { Injectable } from '@angular/core';
import { SharedService } from './shared.service';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { User } from '../models/user/user.model';
import { AuthenticationService } from 'app/service/authentication.service';
import { UserSerializer } from '../serializer/user-serializer';
import { NgForm } from '@angular/forms';

@Injectable()
export class UserService extends SharedService<User>{

  constructor(httpClient: HttpClient, authenticate: AuthenticationService) {
    super(httpClient,
      'http://localhost:8084/SuperCloud/webresources',
      'user',
      authenticate,
      new UserSerializer()
    );
  }

UserSerializer:

import { User } from "../models/user/user.model";
import { Serializer } from "./serializer";
import { Resource } from "../models/resource.model";

export class UserSerializer extends Serializer {
    fromJson(json: any): Resource {
        const user = new User();
        user.id = json.id;
        user.name = json.name;
        user.surname = json.surname;
        user.email = json.email;
        user.phoneNumber = json.phoneNumber;
        user.password = json.password;
        user.username = json.username;
        user.active = json.active;
        console.log('serializer');
        console.log(user);
        return user;
    }
}

用户模型:

import { Resource } from "../resource.model";

export class User extends Resource{
    username: string;
    email: string;
    name: string;
    surname: string;
    phoneNumber: string;
    password?: string;
    active : boolean;
}

UserService继承了:

 ngOnInit() {
        this.userService.list().subscribe(
            (data) => console.log(data)
       );

    }

错误:

  

core.es5.js:1020错误TypeError:无法读取以下内容的属性“地图”   未定义

     

位于UserService.SharedService.convertData(shared.service.ts:53)
  在MapSubscriber.eval [作为项目](shared.service.ts:48)
  在MapSubscriber._next(map.js:79)
  在MapSubscriber.Subscriber.next(Subscriber.js:95)中
  在MapSubscriber._next(map.js:85)
  在MapSubscriber.Subscriber.next(Subscriber.js:95)中
  在FilterSubscriber._next(filter.js:90)
  在FilterSubscriber.Subscriber.next(Subscriber.js:95)中
  在MergeMapSubscriber.notifyNext(mergeMap.js:151)
  在InnerSubscriber._next(InnerSubscriber.js:25)

2 个答案:

答案 0 :(得分:0)

使用订阅而不是地图来返回响应。

$ dig aridns.com NS @a.gtld-servers.net

; <<>> DiG 9.11.3-1ubuntu1.1-Ubuntu <<>> aridns.com NS @a.gtld-servers.net
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 2552
;; flags: qr rd; QUERY: 1, ANSWER: 0, AUTHORITY: 4, ADDITIONAL: 1
;; WARNING: recursion requested but not available

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;aridns.com.            IN  NS

;; AUTHORITY SECTION:
aridns.com.     172800  IN  NS  dns1.ausregistry.net.au.
aridns.com.     172800  IN  NS  dns1-1.ausregistry.net.au.
aridns.com.     172800  IN  NS  dns1-2.ausregistry.net.au.
aridns.com.     172800  IN  NS  dns2-1.ausregistry.net.au.

;; Query time: 68 msec
;; SERVER: 192.5.6.30#53(192.5.6.30)
;; WHEN: Mon Sep 03 19:28:07 EST 2018
;; MSG SIZE  rcvd: 139

BTW RXJs6更改了implementation of using observable map function

答案 1 :(得分:0)

首先,我假设您传递给convertData函数的数据不是数组。 在这种情况下,只有ArrayObservable具有map功能。 另外,RxJS 6中的链接函数已更改为pipeable operators https://github.com/ReactiveX/rxjs/blob/master/doc/pipeable-operators.md

其次,查看错误消息-我认为从端点返回的数据值没有值。

第三,data.map(item => {this.serializer.fromJson(item)});-如果map函数内部的箭头函数用大括号括起来,则需要使用return关键字。 换句话说,data.map(item => {this.serializer.fromJson(item)});应该是data.map(item => this.serializer.fromJson(item));data.map(item => {return this.serializer.fromJson(item)});