angular - 为什么 request.ts 中的 serializeBody 方法在 case 字符串中不转换 JSON.stringify(this.body)?
问题描述
当我将string
值传递给 post 方法时,该值未转换JSON
。所以我们无法在 Controller 中得到这个值。
我检查了以下代码并找到了未转换值的原因。
但我无法理解这种行为是正确的。
apply(id: string): Observable<boolean> {
return this.http.post<boolean>(
REQUEST_URL + '/applicationrequest',
id,
HEADERS
);
}
@ResponseBody
@RequestMapping(value = "/applicationrequest", method = RequestMethod.POST)
public boolean apply(@RequestBody UUID id) {
return usecase.apply(id);
}
我想知道为什么string
不应该JSON
自动转换的原因。如果使用方式httpClient
,我想知道正确的使用方式。谢谢你。
角度版本是 8.1.0。Java 是 Java 8。Spring 是 5.1 / Spring Boot 2.1
解决方案
我团队中的某个人也发现了这个问题,我们需要JSON.stringify(...)
为所有只接受正文中的字符串的 HTTP PUT/POST 方法添加。我们生成的代理(我们使用 Swagger)没有为我们添加这个。
实际问题在Angular 代码中:
/**
* Transform the free-form body into a serialized format suitable for
* transmission to the server.
*/
serializeBody(): ArrayBuffer | Blob | FormData | string | null {
// If no body is present, no need to serialize it.
if (this.body === null) {
return null;
}
// Check whether the body is already in a serialized form. If so,
// it can just be returned directly.
if (isArrayBuffer(this.body) || isBlob(this.body) || isFormData(this.body) ||
typeof this.body === 'string') {
return this.body;
}
// Check whether the body is an instance of HttpUrlEncodedParams.
if (this.body instanceof HttpParams) {
return this.body.toString();
}
// Check whether the body is an object or array, and serialize with JSON if so.
if (typeof this.body === 'object' || typeof this.body === 'boolean' ||
Array.isArray(this.body)) {
return JSON.stringify(this.body);
}
// Fall back on toString() for everything else.
return (this.body as any).toString();
}
普通字符串将使用最后一个选项,并将呈现为纯字符串,而不是通过JSON.stringify
.
我创建了一个HTTP 拦截器来检查内容类型,如果它设置为application/json
ortext/json
并且正文是纯字符串,则拦截器调用JSON.stringify
以确保它是有效的 JSON 字符串。这个拦截器看起来像这样:
import { Injectable } from '@angular/core';
import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest } from '@angular/common/http';
import { Observable } from 'rxjs';
@Injectable()
export class StringInterceptor implements HttpInterceptor{
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
if (typeof request.body === 'string') {
const contentType = request.headers.get('Content-Type')
if (contentType == 'application/json' || contentType == 'text/json') {
request = request.clone({
body: JSON.stringify(request.body)
});
}
}
return next.handle(request)
}
}
您还需要通过在提供程序注册中添加以下代码app.module.ts
(确保导入您的拦截器)来注册拦截器:
{
provide: HTTP_INTERCEPTORS,
useClass: StringInterceptor,
multi: true
},
还要确保删除自己的JSON.stringify(...)
调用以避免所有字符串都有过多的引号。
推荐阅读
- google-cloud-platform - Google PubSub 拉取配置阈值
- google-apps-script - 查找并删除空行
- json - 如何从 Ansible 中由正斜杠分隔的字符串中获取特定值
- flutter - 如何通过在颤动中点击文本来启用复选框?
- java - Dapr Sub/Pub & Kubernetes:如何扩展每个订阅者 Pod 接收消息的 Pod
- solr - Logstash > Solr 错误未定义方法 `execute' for nil:NilClass
- typescript - 交叉口或联合。"" 类型的参数不能分配给 x 类型参数的参数。类型 y 缺少属性,但类型 z 需要
- javascript - JSDoc 没有记录 Javascript 中的对象引用
- php - 为什么我的 w3schools ajax 数据库教程的 1 对 1 副本只拉取第一组数据?
- python - yield with walrus operator := 导致语法错误