You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

调用SpringBoot Webflux接口删除MongoDB条目时报JSON错误

问题场景

客户端向SpringBoot WebFlux后端发起请求删除MongoDB文档时触发JSON解析报错,相关代码如下:

前端代码

fetch("http://localhost:8080/shifts/deleteShift", {
      method: "POST",
      headers: {
        Accept: "application/json",
        "Content-Type": "application/json",
      },
      credentials: "include",
      body: JSON.stringify(UID),
    })
      .then((response) => response.json())
      .then((data) => {
        console.log(data);
        setDeleteShift(false);
      })
      .catch((err) => console.log(err));

后端代码

Controller层

@ResponseStatus(HttpStatus.OK)
@PostMapping("/deleteShift")
private Mono<Void> deleteShift(@RequestBody String ID) {
    return shiftService.deleteShift(ID);
}

Service层

public Mono<Void> deleteShift(String ID){
    return this.shiftRepository.deleteById(ID);
}

Repository层

@Repository
public interface ShiftRepository extends ReactiveMongoRepository<Shift, String> {
}

报错截图

报错截图

问题根因
  • 前端逻辑缺陷:接口返回Mono<Void>时响应体为空,前端直接对空响应调用response.json()会触发JSON解析语法错误,这是报错的直接原因。
  • 后端代码错误:Controller中处理请求的deleteShift方法被定义为private私有方法,Spring无法正常代理映射该接口,会导致请求无法被正确处理。

修复方案

前端修改

调整响应处理逻辑,不要对空响应强行解析JSON,增加响应类型判断:

fetch("http://localhost:8080/shifts/deleteShift", {
  method: "POST",
  headers: {
    Accept: "application/json",
    "Content-Type": "application/json",
  },
  credentials: "include",
  body: JSON.stringify(UID),
})
.then(async (response) => {
  if (!response.ok) throw new Error(`请求异常,状态码:${response.status}`);
  const contentType = response.headers.get("content-type");
  // 只有响应是JSON格式时才做解析
  if (contentType?.includes("application/json")) {
    return response.json();
  }
  return;
})
.then(() => {
  setDeleteShift(false);
})
.catch((err) => console.log(err));

后端修改

  1. 将Controller层请求处理方法的访问修饰符改为public,保证Spring可以正常映射接口。
  2. 无返回值的删除接口使用204 No Content状态码更符合HTTP语义,明确告知客户端无响应内容,避免解析异常。
    修改后Controller代码:
@ResponseStatus(HttpStatus.NO_CONTENT)
@PostMapping("/deleteShift")
public Mono<Void> deleteShift(@RequestBody String ID) {
    return shiftService.deleteShift(ID);
}

可选规范优化

如果希望参数格式更清晰,可以将单个ID封装为请求对象,避免纯字符串传参的格式歧义:

  1. 定义简单请求参数对象(Java 16+可直接用record):
public record DeleteShiftRequest(String id) {}
  1. 调整Controller方法参数接收:
@ResponseStatus(HttpStatus.NO_CONTENT)
@PostMapping("/deleteShift")
public Mono<Void> deleteShift(@RequestBody DeleteShiftRequest request) {
    return shiftService.deleteShift(request.id());
}
  1. 前端对应调整请求体格式:
body: JSON.stringify({ id: UID })

另外删除操作更符合RESTful规范的写法是使用@DeleteMapping,将ID放在路径参数中,比如@DeleteMapping("/{id}"),可以根据项目规范自行调整。

内容的提问来源于stack exchange,提问作者Hassan Raza

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 14:00:54