4

我刚刚发现了新的 Angular 4.3.xHttpClient模块,我很可能忽略了一些简单的东西。

我想知道是否可以注册一个自定义 JSON 反序列化器,并且仍然可以从输入的HttpClientget/post/put 中受益。碰巧出于性能原因,我的后端返回 JSOG,它是 JSON 的扩展,而不是JSON内容。

目前我使用 normal 发出所有请求get(url, {responseType: 'text'}),然后通过 RxJs Map Operation 运行响应以转换Observable<string>我想要的 Observable 中的 ,返回JSOG.parse(responseString).

我是否错过了使用某种拦截器的解决方案?非常感谢您的建议。

4

2 回答 2

2

这是我的解决方案,

@Injectable()
export class JSOGInterceptor implements HttpInterceptor {
  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    if (typeof req.body === 'object' && !(req.body instanceof FormData)) {
      req = req.clone({body: JSOG.encode(req.body) });
    }

    return next.handle(req).map(resp => {
     if (resp instanceof HttpResponse && typeof resp.body === 'object'  && !(resp.body instanceof Blob)) {
        resp = resp.clone({ body: JSOG.decode(resp.body) });
      }
      return resp;
    });
}
于 2017-09-29T13:17:50.423 回答
2

您可以只实现一个 HttpInterceptor 并拦截响应并在返回给调用者之前根据需要改变主体。

我正在做类似的事情来拦截从我的 API 返回的 Microsoft ASP.NET 格式日期并将它们转换为实际的 Date 实例。

import { Injectable } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import { HttpInterceptor, HttpRequest, HttpResponse, HttpErrorResponse, HttpHandler, HttpEvent } from '@angular/common/http';

@Injectable()
export class Interceptor implements HttpInterceptor {
    intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
        return next.handle(req).do(event => {
            if (event instanceof HttpResponse) {
                const resp: HttpResponse<any> = event;

                // Mutate the body, replace ASP.NET Dates with actual local Date objects.
                let body: {} = resp.body;
                this.recurseBody(body);
            }
        });
    }

    private recurseBody(body: {}) {
        if (!body) {
            return;
        }

        for (let key in body) {
            if (body.hasOwnProperty(key)) {
                let element = body[key];
                if (typeof element === 'object') {
                    this.recurseBody(element);
                } else if (typeof element === 'string') {
                    // Check for a MS-format Date with optional TZ offset.
                    const matched = /\/Date\(([-]?\d{1,15})([\+-][01][0-3][0-5][0-9])?\)\//.exec(element);
                    if (matched) {
                        let tzOffsetMs = 0;
                        const tz = matched[2] || '';
                        if (tz) {
                            const hours = parseInt(tz.substr(0, tz.length - 2), 10);
                            const mins = parseInt(tz.substr(tz.length - 2, 2), 10);
                            const tzOffsetMins = mins + hours * 60;
                            tzOffsetMs = tzOffsetMins * 60 * 1000;
                        }

                        // Create a UTC Date object.
                        const date = new Date(+matched[1] + tzOffsetMs);
                        // Get the timezone offset for the local time (in minutes) and convert to ms.
                        const tzOffset = date.getTimezoneOffset() * 60 * 1000;

                        // Create a local date by using the offset
                        const localDate = new Date(date.getTime() + tzOffset);

                        console.log('convert ' + element + ' to ' + date + ' offset ' + date.getTimezoneOffset() + ' local = ' + localDate);

                        // Set the local date.
                        body[key] = localDate;
                    }
                }
            }
        }
    }
}
于 2017-09-26T22:57:10.640 回答