Typescript中反序列化对象的Getter方法



我们对返回对象集合的服务进行了各种Http调用。在我们的angular应用程序中,如果指定了typescript,则会将其解释为适当的类型,例如Person:

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

比方说,我希望能够轻松地为这个用户构建一个问候字符串,但我希望成为一名优秀的程序员,只做一次,而不是多个地方。所以我创建了一个getter来检索它:

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

但是,当typescript反序列化它时,它缺少greeting属性的原型(它被设置为未定义(。我发现typescript正在将JSON对象映射到它所拥有的类,并且映射的对象上不存在任何丢失的字段/属性(如果调用,则返回undefined(。解决这个问题的最佳方法是什么?

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

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

您所做的工作纯属巧合,因为.post的响应也提供了您正在访问的属性名称。事实上,TypeScript在tsc命令之后不再使用,该命令将TypeScript转换为JavaScript源代码。因此,在运行时将丢失所有类型检查。

如果你要硬编码这个任务,就像这样:

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)

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

我建议在尝试使用服务器响应之前,使用管道为自己构建一个类的实例,以便在第一次联系时就可以捕捉到任何错误,而不是在10秒后,当您最终尝试访问不存在的.save()操作时。

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

您必须创建一个所谓的复制构造函数,它接受对象的所有字段:

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

现在你可以做了

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

当然,这有很多变体。你可以直接做

constructor(public firstName: string, public lastName: string) {}

以避免再次手动分配值。或者想想你想用什么其他方式写这篇文章。归根结底,您需要实际创建类的实例,而不是仅将类类型用作类型。

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调用返回的资源中复制的。

相关内容

  • 没有找到相关文章

最新更新