最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Angular: serializeunserialize in JSON HttpRequest and HttpResponse object - Stack Overflow

programmeradmin1浏览0评论

I want caching into the "localstorage" the HttpRequest and HttpResponse classes from @angular/mon/http.

The localstorage only accept string, therefore i want serialize/unserialize both objects (HttpRequest and HttpResponse) with JSON.stringfy() and JSON.parse().

The problem is HttpRequest and HttpResponse are both plex class with some ES6 Map (eg. HttpHeaders) and some getter/setter function, with JSON.stringfy() and JSON.parse() the serialization/unserialization don't return the same object and some information are lost.

There is a way for serialize/unserialize HttpRequest and HttpResponse class?

I'm searching for a plete serialization/unserialization (headers, params, body, etc)

In this example there is two method for serialize and unserialize HttpRequest, eg.:

function serializeRequest(angularRequest: HttpRequest): string {
  return null; // to implement
}
function unserializeRequest(jsonRequest: string): HttpRequest {
  return null; // to implement
}

// this is an example of request
const originalRequest = new HttpRequest('POST', '', {foo: true}, {
  params: new HttpParams().set('verbose', 'true'),
  headers: new HttpHeaders({
    BAR: 'baz',
  }),
  reportProgress: true,
  responseType: 'json',
  withCredentials: true
});

// serializeRequest trasform HttpRequest in json format
const jsonRequest: string = serializeRequest(originalRequest);

// unserializeRequest trasform json format to HttpRequest
const unserializedRequest : HttpRequest = unserializeRequest(jsonRequest);

// unserializedRequest as same object of originalRequest
expect(originalRequest).toEqual(unserializedRequest);

the same serialization/unserialization for the response

function serializeResponse(angularResponse: HttpResponse): string {
  return null; // to implement
}
function unserializeResponse(jsonResponse: string): HttpResponse {
  return null; // to implement
}

// this is an example of response
const originalResponse = new HttpResponse({
  headers: new HttpHeaders({
    BAR: 'baz',
  }),
  status: 200,
  statusText: 'OK',
  url: '',
  body: {foo: true}}
);

// serializeResponse trasform HttpResponse in json format
const jsonResponse: string = serializeResponse(originalRequest);

// unserializeResponse trasform json format to HttpResponse 
const unserializedResponse: HttpResponse = unserializeResponse(jsonResponse);

// unserializedResponse as same object of originalResponse
expect(originalResponse).toEqual(unserializedResponse);

I want caching into the "localstorage" the HttpRequest and HttpResponse classes from @angular/mon/http.

The localstorage only accept string, therefore i want serialize/unserialize both objects (HttpRequest and HttpResponse) with JSON.stringfy() and JSON.parse().

The problem is HttpRequest and HttpResponse are both plex class with some ES6 Map (eg. HttpHeaders) and some getter/setter function, with JSON.stringfy() and JSON.parse() the serialization/unserialization don't return the same object and some information are lost.

There is a way for serialize/unserialize HttpRequest and HttpResponse class?

I'm searching for a plete serialization/unserialization (headers, params, body, etc)

In this example there is two method for serialize and unserialize HttpRequest, eg.:

function serializeRequest(angularRequest: HttpRequest): string {
  return null; // to implement
}
function unserializeRequest(jsonRequest: string): HttpRequest {
  return null; // to implement
}

// this is an example of request
const originalRequest = new HttpRequest('POST', 'https://angular.io/docs?foo=bar', {foo: true}, {
  params: new HttpParams().set('verbose', 'true'),
  headers: new HttpHeaders({
    BAR: 'baz',
  }),
  reportProgress: true,
  responseType: 'json',
  withCredentials: true
});

// serializeRequest trasform HttpRequest in json format
const jsonRequest: string = serializeRequest(originalRequest);

// unserializeRequest trasform json format to HttpRequest
const unserializedRequest : HttpRequest = unserializeRequest(jsonRequest);

// unserializedRequest as same object of originalRequest
expect(originalRequest).toEqual(unserializedRequest);

the same serialization/unserialization for the response

function serializeResponse(angularResponse: HttpResponse): string {
  return null; // to implement
}
function unserializeResponse(jsonResponse: string): HttpResponse {
  return null; // to implement
}

// this is an example of response
const originalResponse = new HttpResponse({
  headers: new HttpHeaders({
    BAR: 'baz',
  }),
  status: 200,
  statusText: 'OK',
  url: 'https://angular.io/docs',
  body: {foo: true}}
);

// serializeResponse trasform HttpResponse in json format
const jsonResponse: string = serializeResponse(originalRequest);

// unserializeResponse trasform json format to HttpResponse 
const unserializedResponse: HttpResponse = unserializeResponse(jsonResponse);

// unserializedResponse as same object of originalResponse
expect(originalResponse).toEqual(unserializedResponse);
Share Improve this question edited Aug 16, 2020 at 16:43 Simone Nigro asked Aug 12, 2020 at 14:33 Simone NigroSimone Nigro 4,9074 gold badges46 silver badges80 bronze badges 5
  • did you try HttpInterceptor you can intercept all request and response header, body and params etc – Iam Coder Commented Aug 17, 2020 at 18:33
  • Yes, the point is serialize/unserialize request/response – Simone Nigro Commented Aug 17, 2020 at 19:34
  • Why are you trying to cache http request & response to local storage ? What is the use case? For in memory caching you can use npmjs./package/ngx-cacheable its really simple & useful Library. – Saurabh Gangamwar Commented Aug 23, 2020 at 6:07
  • @Simone Nigro Do you want to serialize the class or the response? And also, what's your motivation?, maybe we can workaround this :) – WSD Commented Aug 23, 2020 at 7:06
  • I need to serialize and unserialize to/from string both class (response/request) . The motivation is store both class into localstorage, for persistent cache. – Simone Nigro Commented Aug 23, 2020 at 8:24
Add a ment  | 

3 Answers 3

Reset to default 2 +50

Although I would remend a Service Worker for Caching, the easiest way that I know is to clone the request/response and then get their information:

function serializeRequest(req: HttpRequest<any>): string {
    const request = req.clone(); // Make a clone, useful for doing destructive things
    return JSON.stringify({
        headers: Object.fromEntries( // Just a helper to make this into an object, not really required but makes the output nicer
            request.headers.keys.map( // Get all of the headers
                (key: string) => [key, request.headers.getAll(key)] // Get all of the corresponding values for the headers
            )
        ),
        method: request.method, // The Request Method, e.g. GET, POST, DELETE
        url: request.url, // The URL
        params: Object.fromEntries( // Just a helper to make this into an object, not really required but makes the output nicer
            request.headers.keys.map( // Get all of the headers
                (key: string) => [key, request.headers.getAll(key)] // Get all of the corresponding values for the headers
            )
        ), // The request parameters
        withCredentials: request.withCredentials, // Whether credentials are being sent
        respnseType: request.responseType, // The response type
        body: request.serializeBody() // Serialize the body, all well and good since we are working on a clone
    })
}

In a similar fashion we can serialize the response as well (assuming T is JSON patible, a fair assumption in an HTTP Request):

function serializeResponse(res: HttpResponse<any>): string {
    const response = res.clone();
    return JSON.stringify({
        headers: Object.fromEntries( // Just a helper to make this into an object, not really required but makes the output nicer
            response.headers.keys.map( // Get all of the headers
                (key: string) => [key, response.headers.getAll(key)] // Get all of the corresponding values for the headers
            )
        ),
        status: response.status,
        statusText: response.statusText,
        url: response.url,
        body: response // Serialize the body, all well and good since we are working on a clone
    })
}

And then, since we saved all required information, deserialization is a walk in the park:

function deserializeRequest<T = any>(req: string): HttpRequest<T> {
    const request = JSON.parse(req);
    const headers = new HttpHeaders(request.headers);
    const params = new HttpParams(); // Probably some way to make this a one-liner, but alas, there are no good docs
    for(let parameter in request.params){
        request.params[parameter].forEach((paramValue: string) => params.append(parameter, paramValue));
    }
    return new HttpRequest(request.method, request.url, request.body, {
        headers,
        params,
        respnseType: request.respnseType,
        withCredentials: request.withCredentials
    });
}

function deserializeResponse<T = any>(res: string): HttpResponse<T> {
    const response = JSON.parse(res);
    const headers = new HttpHeaders(response.headers);
    return new HttpRequest({
        headers,
        body: response.body,
        status: response.status,
        statusText: response.statusText,
        url: response.url,
    });
}

Playground of the whole thing (although, regrettably the angular types do not load correctly)

Note that I have not tested this in any environment, so this is provided AS-IS, and I am not sure how expect would handle two HttpHeaders/HttpParams, especially since they may not have the exact same order.

If you just want to serialize the HttpRequest then the class itself provides serializeBody() method, here

The below mentioned way is the best way of serialize the HttpResponse in Angular. res.json() function will show you the body,headers and params.

this.http.get('/app/lists.json').map((res:Response) => res.json());
发布评论

评论列表(0)

  1. 暂无评论