Json 当HttpClient映射不起作用时,如何正确解析TypeScript类的日期对象?

Json 当HttpClient映射不起作用时,如何正确解析TypeScript类的日期对象?,json,angular,typescript,Json,Angular,Typescript,Task.ts: tasks.service.ts: 我从GetTask返回的Task对象分配了dueDate字段,但该值的类型是string,而不是我预期的Date 通过一些搜索,我明白了HttpClient无意正确解析我的对象。不幸的是,这个问题并没有给我提供有用的指导,告诉我应该做什么才能得到我的约会对象。我该怎么做?在组件中将其声明为一个日期,如下所示: getTasks(): Observable<Task[]> { return this.http.get<

Task.ts:

tasks.service.ts:

我从GetTask返回的Task对象分配了dueDate字段,但该值的类型是string,而不是我预期的Date


通过一些搜索,我明白了HttpClient无意正确解析我的对象。不幸的是,这个问题并没有给我提供有用的指导,告诉我应该做什么才能得到我的约会对象。我该怎么做?

在组件中将其声明为一个日期,如下所示:

getTasks(): Observable<Task[]> {
    return this.http.get<Task[]>(`${WEBAPI_URL}/Tasks`)
        .pipe(
            map(items => {
                const tasks: Task[] = [];
                return items.map(
                    item => {
                        item.dueDate = new Date(item.dueDate);
                        return Object.assign(new Task(), item);
                    });
            }),
            tap(data => console.log(JSON.stringify(data))),
            catchError(this.handleError)
        );
}
getTasks(): Observable<Task[]> {
    return this.http.get<Task[]>(this.url)
        .pipe(
            map(TaskSerializer.serialize),
            catchError(this.handleError)
        );
}
示例.component.ts

或者把它保存为一个瞬间

Task.ts

我建议用第一种方法。我还建议去图书馆看看


编辑:我会将它声明为日期对象,并让它将其作为字符串存储在数据库中。这就是我看到的处理日期的大多数用例,也是我公司的每个人处理日期的方式。99%的情况下,您只需要月/日/年,因此您只需将其存储在数据库中是有意义的,但在ui端将其格式化为日期对象有点麻烦。

在组件中将其声明为日期,如下所示:

getTasks(): Observable<Task[]> {
    return this.http.get<Task[]>(`${WEBAPI_URL}/Tasks`)
        .pipe(
            map(items => {
                const tasks: Task[] = [];
                return items.map(
                    item => {
                        item.dueDate = new Date(item.dueDate);
                        return Object.assign(new Task(), item);
                    });
            }),
            tap(data => console.log(JSON.stringify(data))),
            catchError(this.handleError)
        );
}
getTasks(): Observable<Task[]> {
    return this.http.get<Task[]>(this.url)
        .pipe(
            map(TaskSerializer.serialize),
            catchError(this.handleError)
        );
}
示例.component.ts

或者把它保存为一个瞬间

Task.ts

我建议用第一种方法。我还建议去图书馆看看


编辑:我会将它声明为日期对象,并让它将其作为字符串存储在数据库中。这就是我看到的处理日期的大多数用例,也是我公司的每个人处理日期的方式。99%的情况下,您只需要月/日/年,因此只在数据库中存储月/日/年是有意义的,但在ui端将其格式化为日期对象有点麻烦。

您在这里有几个选项

1您可以在UI中将日期作为字符串处理。因此,更改Task的定义,将日期保留为字符串,并以这种方式使用它,根据需要将其转换为用于计算的日期

2您可以将从Http请求返回的每个对象映射到任务对象。大概是这样的:

getTasks(): Observable<Task[]> {
    return this.http.get<Task[]>(`${WEBAPI_URL}/Tasks`)
        .pipe(
            map(items => {
                const tasks: Task[] = [];
                return items.map(
                    item => {
                        item.dueDate = new Date(item.dueDate);
                        return Object.assign(new Task(), item);
                    });
            }),
            tap(data => console.log(JSON.stringify(data))),
            catchError(this.handleError)
        );
}
getTasks(): Observable<Task[]> {
    return this.http.get<Task[]>(this.url)
        .pipe(
            map(TaskSerializer.serialize),
            catchError(this.handleError)
        );
}
这还有一个好处,就是数组中有实际的任务对象,这意味着如果添加任务方法或getter/setter,它们将与任务数组正确关联

编辑: 最好构建一个实用程序类来处理对象的序列化/反序列化。那么上面的代码看起来更像这样:

getTasks(): Observable<Task[]> {
    return this.http.get<Task[]>(`${WEBAPI_URL}/Tasks`)
        .pipe(
            map(items => {
                const tasks: Task[] = [];
                return items.map(
                    item => {
                        item.dueDate = new Date(item.dueDate);
                        return Object.assign(new Task(), item);
                    });
            }),
            tap(data => console.log(JSON.stringify(data))),
            catchError(this.handleError)
        );
}
getTasks(): Observable<Task[]> {
    return this.http.get<Task[]>(this.url)
        .pipe(
            map(TaskSerializer.serialize),
            catchError(this.handleError)
        );
}

这里有几个选项

1您可以在UI中将日期作为字符串处理。因此,更改Task的定义,将日期保留为字符串,并以这种方式使用它,根据需要将其转换为用于计算的日期

2您可以将从Http请求返回的每个对象映射到任务对象。大概是这样的:

getTasks(): Observable<Task[]> {
    return this.http.get<Task[]>(`${WEBAPI_URL}/Tasks`)
        .pipe(
            map(items => {
                const tasks: Task[] = [];
                return items.map(
                    item => {
                        item.dueDate = new Date(item.dueDate);
                        return Object.assign(new Task(), item);
                    });
            }),
            tap(data => console.log(JSON.stringify(data))),
            catchError(this.handleError)
        );
}
getTasks(): Observable<Task[]> {
    return this.http.get<Task[]>(this.url)
        .pipe(
            map(TaskSerializer.serialize),
            catchError(this.handleError)
        );
}
这还有一个好处,就是数组中有实际的任务对象,这意味着如果添加任务方法或getter/setter,它们将与任务数组正确关联

编辑: 最好构建一个实用程序类来处理对象的序列化/反序列化。那么上面的代码看起来更像这样:

getTasks(): Observable<Task[]> {
    return this.http.get<Task[]>(`${WEBAPI_URL}/Tasks`)
        .pipe(
            map(items => {
                const tasks: Task[] = [];
                return items.map(
                    item => {
                        item.dueDate = new Date(item.dueDate);
                        return Object.assign(new Task(), item);
                    });
            }),
            tap(data => console.log(JSON.stringify(data))),
            catchError(this.handleError)
        );
}
getTasks(): Observable<Task[]> {
    return this.http.get<Task[]>(this.url)
        .pipe(
            map(TaskSerializer.serialize),
            catchError(this.handleError)
        );
}
我发现了一个不太重的拦截器,允许在Angular中使用HTTP调用时直接在对象中设置正确的日期。你可以在这里找到它:

请注意,我唯一需要更改的是regex,为了使末尾的Z成为可选的,我在服务器端使用了DateTimeFormatter.ISO_DATE_TIME格式。

我发现了一个不太重的拦截器,允许在服务器端使用HTTP调用时直接在对象中设置正确的日期。你可以在这里找到它:


请注意,我唯一需要更改的是正则表达式,为了使末尾的Z成为可选的,我在服务器端使用DateTimeFormatter.ISO_DATE_TIME格式。

我认为您必须使用映射运算符手动映射对象。我认为您必须使用映射运算符手动映射对象。body是任务数组吗?看起来您需要添加一个.foreach并遍历所有这些?取决于您的web服务调用。如果我需要一个对象,response.body会从rest api完美地返回我的对象,如果我需要一个对象数组,它会返回一个对象数组。如果你有一个不同的配置,那么你需要你。主要的一点是新的日期代码,用于格式化您的响应。什么是瞬间?瞬间就像一个时间戳。所以,在这种情况下,这可能不是最好的方法,不是吗?看起来您需要添加一个.foreach并遍历所有这些?取决于您的web服务调用。如果我需要一个对象,response.body会从rest api完美地返回我的对象,如果我需要一个对象数组,它会返回一个对象数组。如果你有一个不同的配置,那么你需要你。主要的一点是新的日期代码,用于格式化您的响应。什么是瞬间?瞬间就像一个时间戳。所以也许这不是最好的选择
r这种情况下,这似乎是一个合理的解决方案,但我可以看到,当类具有许多不同的、更复杂类型的属性时,它会失控。我将手动解析所有内容,而我所做的任何重构都会破坏解析器。最好将此代码放入自己的方法中。考虑使用一个实用工具类来序列化和反序列化数据。这就是HttpClient无法自动执行此操作的原因。它不可能知道所有的复杂类型以及如何恰当地映射它们。然而,有一些映射工具,你可以看看。我没有使用过任何东西,但谷歌Angular 4 mapper提供了一些选项。这似乎是一个合理的解决方案,但我可以看到,当类具有许多不同的、更复杂类型的属性时,它会失控。我将手动解析所有内容,而我所做的任何重构都会破坏解析器。最好将此代码放入自己的方法中。考虑使用一个实用工具类来序列化和反序列化数据。这就是HttpClient无法自动执行此操作的原因。它不可能知道所有的复杂类型以及如何恰当地映射它们。然而,有一些映射工具,你可以看看。我没有使用过任何工具,但谷歌Angular 4 mapper提供了一些选项。