HTTP:从JSON对象到Typescript的类型断言
我已经阅读了有关接口和类型断言的内容。我一直在看这样的网页:HTTP:从JSON对象到Typescript的类型断言,json,http,typescript,angular,Json,Http,Typescript,Angular,我已经阅读了有关接口和类型断言的内容。我一直在看这样的网页: (这个和TS无关!) 我已经掌握了窍门,理解基本知识非常简单。但是:当涉及HTTP时,我找不到如何将JSON对象键入我在应用程序中使用的对象 例如,我有一个教师对象数组。每个教师都有一个id、姓名和一组学生。我有另一个班的学生,包含他们的属性。。。。。等等 在这些链接的某个地方,我读到,除非你需要对一个对象执行操作,只要有一个接口就足够了。但是,除非您想对对象执行操作,否则您需要一个单独的类 我的实际教师课程开始于…: ex
- (这个和TS无关!)
export class Teacher {
private students: Array<Student>;
constructor(public id: string, public name: string) {
this.students = new Array<Student>();
}
public getStudents(): Array<Student> {
return this.students;
}
}
组件(角度2组件):
我的界面看起来像:
export interface TeacherJSON {
id: string,
name: string,
students: Array<Student>;
}
我确实理解上面的例子,但我想http、映射和订阅让我很反感,我不知道如何在我的代码中实现它
显然,我需要首先将组件中的teachers数组更改为接口的实例
接口的实例是不存在的。接口是抽象的,它们只存在于TypeScript中,甚至不编译为JavaScript。您编写它们是为了在编辑器中获得代码完成和其他好处;在大型应用程序中为您提供帮助,这样您就不必记住每个对象都有哪些属性和方法
当您必须实例化一个对象时,接口不能这样做-您将使用一个类,并像往常一样创建属性和方法。在您的示例中,正确的方法是:
interface ITeacher{
id: string,
name: string,
students: Array<Student>;
};
class Teacher implements ITeacher {
id: string,
name: string,
students: Array<Student>;
}
如果您有几种类型的教师,并且您希望确保每种教师都具有所有必要的属性/方法,那么创建一个接口是有意义的:
class FirstGradeTeacher implements ITeacher{}
class SecondGradeTeacher implements ITeacher{}
你可能已经注意到我根本没有提到JSON<算了吧…使用对象模型(类或接口)时。它只是逻辑模型的数据格式。当您构建模型并规划它们应该如何工作时,您并不关心协议和格式(Http服务处理这些)
希望这有帮助(:假设您通过http获取教师列表,您可以对其进行筛选以获取所需的教师列表:
getById(id: string) {
return this.http.get('someUrl' + id)
.map((res: Response) => res.json())
.filter(teacher => teacher.id === id));
如果我很了解您的问题,您需要为反序列化JSON对象提供一些方法,该对象的原型为
对象
。目前,普通javascript API无法实现这一点,因为您从REST服务接收的内容是一个普通字符串,它通过JSON.parse
成为对象。您应该使用另一种反序列化机制,能够在运行时检查类,并从反序列化的JSON重新构建它们的实例。通过这种方式,您将拥有新的JSON对象,但拥有正确的原型,该原型包含该类的所有方法。我将试着做一个示例
假设您正在调用一个REST端点,该端点为您提供类似Teacher
的对象。在某些情况下,您可以执行var freshObject=JSON.parse(receivedString)
(实际上,Angular已经完成了,但我们将改进此机制);最简单的操作(但不是最明智的操作)是将freshObject
的原型更改为Teacher
原型:Object.setPrototypeof(freshObject,Teacher.prototype)
。现在您可以在freshObject
上调用Teacher
方法,但这显然是一个肤浅的更改,因为嵌套对象(Student
s在本例中)仍然有对象
作为其原型,问题再次出现
现在很明显,我们需要能够递归地调查教师
类结构,同时使用正确的原型重新构建接收到的对象(实际上,您可以创建新的副本,而不是更改原型,这应该不会太重)。您可能需要类似于:Teacher.getClass()。成员将为您提供以下信息:
学生姓名
字段
students
字段的类型(Array
)
- 组件类的构造函数
Student
如果您有此类信息,您可以递归地执行与前面示例中相同的操作
我最近发布了一个增强版的TypeScript编译器,允许使用此用例。我为您准备了一个完整的工作示例,您可以找到编译器项目。请告诉我这是否解决了您的问题。谢谢您的回答。当然,很难看到我的问题,因为您看不到完整的代码。我无法扩展我的Teac因为学生在课堂上是私人的,所以她的课和我的接口在一起。我让人看了我的代码,我被告知要实现一个接口来解决我的问题。我正在丢失数据,例如当我检索一名教师时。在那里,我必须将新来的教师映射为“新教师”老师,否则我会得到一个self.context错误。如果你看我的教师类,我只能说new teacher(teacher.id,teacher.name)
。所以我已经在那里丢失了数据。在我的服务中添加了getTeacher
方法来展示我丢失数据的一个问题。@Sasxa res.json()为什么转换为教师?我正在寻找一些说明这一点的文档。它没有转换,它仍然只是一个JSON。但是,因为您希望响应的结构与教师相同,所以您可以将其键入,并且您的工具和编辑器可以帮助您进行类型检查、自动完成、调试等@TomDeseyn@Sasxa我找不到强制转换操作。调用map返回Observable,它在哪里强制转换为Observable?再次感谢,但这对我没有帮助。顺便说一下,我已经尝试过这个解决方案。我到处都在丢失数据,所以我真的需要告诉我的代码
interface ITeacher{
id: string,
name: string,
students: Array<Student>;
};
class Teacher implements ITeacher {
id: string,
name: string,
students: Array<Student>;
}
teachers: Teacher[];
teachers: ITeacher[];
class FirstGradeTeacher implements ITeacher{}
class SecondGradeTeacher implements ITeacher{}
getTeachers(): Observable<Teacher> {
return this.http.get('someUrl')
.map((res: Response) => res.json())
}
this._service.getTeachers()
.subscribe((teachers: Teacher[]) => this.teachers = teachers);
getById(id: string) {
return this.http.get('someUrl' + id)
.map((res: Response) => res.json())
.filter(teacher => teacher.id === id));