Spring Rest中LinkedHashMap转Cuestionario出现ClassCastException问题
这个问题我之前也踩过坑!核心原因很直白:当你用Map<String, Object>作为@RequestBody的接收类型时,Spring默认的Jackson消息转换器不知道你map.get("cuestionario")对应的是Cuestionario类型,所以会把JSON结构默认反序列化成LinkedHashMap,强转自然就抛出类型转换异常了。
下面给你几个实用的解决办法,按推荐程度排序:
1. 用自定义DTO替代Map(最推荐)
既然你的请求体里固定包含motivo和cuestionario两个字段,不如直接定义一个DTO类来接收,Spring会自动帮你完成反序列化,完全不用手动处理类型转换:
// 定义接收请求的DTO类 public class RejectRequest implements Serializable { private String motivo; private Cuestionario cuestionario; // 生成getter、setter,或者用Lombok的@Data注解简化代码 }
然后修改控制器方法的参数:
@RequestMapping(value = Proxy.METHOD_REJECT, method = RequestMethod.POST) public @ResponseBody ResponseEntity<Respuesta> reject( @PathVariable Integer id, @PathVariable Integer uid, @PathVariable Integer asociation, @PathVariable Integer type, @RequestBody(required=false) RejectRequest request) { final String motivo = request.getMotivo(); final Cuestionario cuestionario = request.getCuestionario(); // 后续业务逻辑... }
这种方式不仅解决了类型转换问题,代码可读性也大幅提升,还能结合Spring的参数校验注解(比如@NotNull)做入参校验,一举多得。
2. 手动用ObjectMapper转换LinkedHashMap到Cuestionario
如果因为某些限制必须用Map接收,可以用Spring默认的ObjectMapper来把LinkedHashMap转换成Cuestionario实例:
首先在控制器中注入ObjectMapper(Spring Boot会自动配置,直接注入即可):
@Autowired private ObjectMapper objectMapper;
然后在方法中完成转换:
@RequestMapping(value = Proxy.METHOD_REJECT, method = RequestMethod.POST) public @ResponseBody ResponseEntity<Respuesta> reject( @PathVariable Integer id, @PathVariable Integer uid, @PathVariable Integer asociation, @PathVariable Integer type, @RequestBody(required=false) Map<String, Object> map) { final String motivo = (String) map.get("motivo"); // 把LinkedHashMap转成Cuestionario实例 final Cuestionario cuestionario = objectMapper.convertValue(map.get("cuestionario"), Cuestionario.class); // 后续业务逻辑... }
convertValue方法会自动把Map的键值对映射到Cuestionario的属性上,只要字段名对应(大小写敏感,也可以用@JsonProperty注解调整字段映射关系)就没问题。
为什么之前Map能正常运行?
你提到用Map<List<Integer>, List<Integer>>没问题,是因为List里的泛型是简单类型(Integer),Jackson反序列化时能直接识别并转换,不需要额外的类型信息。但自定义POJO不一样,没有明确的类型提示,Jackson只能默认转成LinkedHashMap。
另外,你之前尝试的LinkedMultiValueMap没用,因为它是用来处理多值参数(比如表单中同一个key对应多个值)的,和请求体的JSON反序列化不是一回事。
内容的提问来源于stack exchange,提问作者chiperortiz

