打字稿中反序列化对象的Getter方法

时间:2018-12-13 18:58:10

标签: angular typescript angular5 angular-http

我们对我们的服务有各种Http调用,它们返回对象的集合。在我们的角度应用程序中,打字稿将它们解释为适当的类型(如果指定),例如Person:

export class Person{
  public firstName: string;
  public lastName: string;
  public salutation: string;
}

比方说,我希望能够轻松地为此用户构建问候语字符串,但是我想成为一名优秀的程序员,并且一次执行而不是多次执行。因此,我创建了一个将获取它的吸气剂:

export class Person{
  public firstName: string;
  public lastName: string;
  public salutation: string;
  public get greeting(): string {
      return salutation + " " + firstName + " " + lastName;
  }
}

但是,当打字稿反序列化时,它缺少greeting属性的原型(将其设置为undefined)。我发现打字稿正在将JSON对象映射到它具有的类,并且映射的对象上不存在任何缺少的字段/属性(如果调用,则返回undefined)。解决此问题的最佳方法是什么?

作为我们如何调用服务的示例:

this.authHttp.post(this.url, user, params).then(
  (res: Person) => {
      console.log(res);
      console.log(res.greeting);
  }
);

3 个答案:

答案 0 :(得分:1)

您必须创建一个包含对象所有字段的复制构造函数:

public static final ResourceBundle QUERY_EXCEL = ResourceBundle.getBundle("ConsultaExcel"); 
String query=QueryManager.QUERY_EXCEL.getString("SQL.SELECT.consultarDatos"); 

现在您可以做

constructor(firstName: string, lastName: string) {
    this.firstName = firstName;
    this.lastName = lastName;
}

当然有很多变体。你可以做

http.post(...)
    .pipe(map(res => new Person(res.firstName, res.lastName)))
    .subscribe(...);

例如,避免再次手动分配值。或想出其他任何您想写的方式。归根结底,这就是您实际上需要创建类的 instance ,而不是仅将类类型用作类型。

答案 1 :(得分:1)

您巧用巧巧的方式 ,因为您正在访问的属性名称也由.post的响应提供。实际上,在将tsc转换为JavaScript源的命令之后,不再使用TypeScript。因此,您将在运行时丢失所有类型检查。

如果您要对此任务进行硬编码,就像这样:

let me: Person = { firstName: 'Ian', lastName: 'MacDonald', salutation: 'Hello.' };

您将在尝试创建JavaScript时收到TypeScript错误。

Property 'greeting' is missing in type
    '{ firstName: string; lastName: string; salutation: string; }'
    but required in type 'Person'.ts(2741)

对于您在类中定义的任何函数,也会出现相同的错误。这是因为{ ... }不是您的类型;它只有明确定义的内容。服务器响应的结果将遵循相同的分配规则,但是直到运行时该问题才会出现(因为数据不存在)。

我建议在尝试使用服务器响应之前,先使用管道为自己构造类的实例,以便在首次尝试访问.save()时,可以在第一次联系时捕获任何错误,而不是在10秒钟后发现错误。不存在的动作。

.post(...).pipe(map((incoming: any) => {
  let person: Person = new Person();
  person.firstName = incoming.firstName;
  person.lastName = incoming.lastName;
  person.salutation = incoming.salutation;
  return person;
});

答案 2 :(得分:0)

HTTP调用的响应不会生成Person类的对象。响应实际上是一个纯JavaScript对象,显然没有Person类的greeting()方法。

为了解决该问题,您可以应用以下代码:

http.post(...)
    .pipe(map(res => Object.assign(new Person(), res)))
    .subscribe(...);

Object.assign(new Person(),res)函数会将所有res值复制到Person实例。在此映射之后,您将拥有一个真实的Person实例,其属性值从http调用返回的资源中复制。