javascript - Angular:在 JSON HttpRequest 和 HttpResponse 对象中序列化/反序列化
问题描述
我想将HttpRequest和HttpResponse类缓存到“ localstorage ”中。@angular/common/http
localstorage
唯一接受,因此我想用andstring
序列化/反序列化两个对象(HttpRequest 和 HttpResponse)。JSON.stringfy()
JSON.parse()
问题是HttpRequest
并且HttpResponse
都是具有一些ES6 Map(例如HttpHeaders)和一些 getter/setter 函数的复杂类,JSON.stringfy()
并且JSON.parse()
序列化/反序列化不返回相同的对象,并且一些信息丢失了。
有没有一种序列化/反序列化HttpRequest
和HttpResponse
类的方法?
我正在寻找完整的序列化/反序列化(标题、参数、正文等)
在此示例中,有两种方法用于序列化和反序列化 HttpRequest,例如:
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);
响应的相同序列化/反序列化
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);
解决方案
虽然我会推荐一个用于缓存的Service Worker,但我知道的最简单的方法是克隆请求/响应,然后获取它们的信息:
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
})
}
以类似的方式,我们也可以序列化响应(假设T
与 JSON 兼容,这是 HTTP 请求中的一个公平假设):
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
})
}
然后,由于我们保存了所有必需的信息,反序列化就像在公园里散步:
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,
});
}
整个事情的游乐场(尽管遗憾的是角度类型没有正确加载)
请注意,我没有在任何环境中对此进行测试,因此按原样提供,我不确定如何
expect
处理两个HttpHeaders
/HttpParams
,特别是因为它们可能没有完全相同的顺序。
推荐阅读
- java - 如何管理 Firebase 存储中的多个上传/下载?
- c# - C# calling a function from it's memory address
- node.js - 带有 RESTful 的 GraphQL 返回空响应
- python - twisted.internet.error.TimeoutError:用户超时导致连接失败
- python-3.x - python niftynet非法指令核心转储
- python - Kivy:当我在主循环上添加功能时出现黑屏
- julia - Julia@1.0.0:如何在 REPL 中安装 Pkg.uuid
- typescript - 如何使用 Inversify + inversify-express-utils 实现 Controller 的组件扫描/自动发现
- eclipse - 如何为 Eclipse 远程系统资源管理器设置默认编辑器?
- python - 如何在阿里巴巴中抓取下一页链接