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

SpringBoot+PostgreSQL POST请求JSON反序列化及字段校验报错

问题分析与解决方案

问题1:JSON反序列化无法构造Treino实例

原因

首次请求的JSON中直接用数字(如103)赋值给idTreino字段,但TreinoExercicio的idTreino是Treino类型,Jackson默认无法将数字直接转换为实体对象,缺少对应的反序列化逻辑。

解决方案

推荐使用DTO(数据传输对象)接收请求,再转换为实体类,这是更规范的做法:

  1. 创建TreinoExercicioDTO类:
public class TreinoExercicioDTO {
    private Long idTreino;
    private Long idExercicio;
    private String dificuldade;
    private BigDecimal peso;
    private BigDecimal series;

    // 生成Getter和Setter方法
}
  1. 修改控制器接收DTO:
@PostMapping
public ResponseEntity<?> cadastrar(@RequestBody final TreinoExercicioDTO dto){
    try{
        this.treinoExercicioService.cadastrar(dto);
        return ResponseEntity.ok("Cadastrado");
    }catch(RuntimeException e){
        return ResponseEntity.badRequest().body("Error " + e.getMessage());
    }
}
  1. 修改服务类,转换DTO为实体并查询关联对象:
@Service
public class TreinoExercicioService {

    @Autowired
    private TreinoExercicioRepository treinoExercicioRepository;
    @Autowired
    private TreinoRepository treinoRepository;
    @Autowired
    private ExercicioRepository exercicioRepository;

    @Transactional(rollbackFor = Exception.class)
    public void cadastrar(final TreinoExercicioDTO dto){
        // 查询关联的Treino和Exercicio实例
        Treino treino = treinoRepository.findById(dto.getIdTreino())
                .orElseThrow(() -> new RuntimeException("Treino não encontrado"));
        Exercicio exercicio = exercicioRepository.findById(dto.getIdExercicio())
                .orElseThrow(() -> new RuntimeException("Exercício não encontrado"));

        // 字段校验
        Assert.isTrue(!dto.getDificuldade().isBlank(), "Campo DIFICULDADE vazio");
        Assert.isTrue(dto.getPeso() != null, "Error campo PESO invalido ou vazio");
        Assert.isTrue(dto.getSeries() != null, "Error campo SERIES vazio");

        // 构建TreinoExercicio实体
        TreinoExercicio treinoExercicio = new TreinoExercicio();
        treinoExercicio.setIdTreino(treino);
        treinoExercicio.setIdExercicio(exercicio);
        treinoExercicio.setDificuldade(dto.getDificuldade());
        treinoExercicio.setPeso(dto.getPeso());
        treinoExercicio.setSeries(dto.getSeries());

        this.treinoExercicioRepository.save(treinoExercicio);
    }
}

问题2:完整结构请求返回“Error campo TREINO vazio”

原因

  1. JSON字段错误:请求中把TreinoExercicio的idExercicio字段写成了idGrupoMuscular,导致idExercicio为null;
  2. LocalDateTime反序列化失败:AbstractEntity中的dataCadastrado是LocalDateTime类型,若未正确配置Jackson处理该类型,会导致Treino对象无法正常反序列化,最终idTreino为null,触发断言;
  3. 服务类断言逻辑错误:Assert.isTrue(treinoExercicio.getDificuldade().isBlank(), ...)逻辑反向,会在dificuldade不为空时抛出异常。

解决方案

  1. 修正请求JSON字段:将idGrupoMuscular改为idExercicio,正确的JSON结构如下:
{
    "idTreino":{
        "id": 52,
        "dataCadastrado": "2023-07-03T02:52:10.719673",
        "dataAtualizado": "2023-07-03T02:56:48.691866",
        "ativo": true,
        "codigoOrdem": "BBB"
    },
    "idExercicio":{
        "id": 1,
        "dataCadastrado": "2023-07-02T16:54:39.44769",
        "dataAtualizado": null,
        "ativo": true,
        "idGrupoMuscular": {
            "id": 1,
            "dataCadastrado": "2023-07-02T16:54:39.44769",
            "dataAtualizado": null,
            "ativo": true,
            "nome": "a"
        },
        "nome": "示例 exercício"
    },
    "dificuldade": "aaaa",
    "peso": "20",
    "series": "20"
}
  1. 配置Jackson支持LocalDateTime:
    Spring Boot默认已包含jackson-datatype-jsr310依赖,只需在application.properties添加配置:
spring.jackson.serialization.write-dates-as-timestamps=false
spring.jackson.date-format=yyyy-MM-dd'T'HH:mm:ss.SSSXXX
  1. 修正服务类断言逻辑:
    将Assert.isTrue(treinoExercicio.getDificuldade().isBlank(), "Campo DIFICULDADE vazio");改为:
Assert.isTrue(!treinoExercicio.getDificuldade().isBlank(), "Campo DIFICULDADE vazio");

额外优化建议

  • 所有实体类添加显式无参构造函数,避免Jackson或JPA反射实例化时出现异常;
  • AbstractEntity的id字段可添加@Setter或@JsonProperty注解,允许Jackson为其赋值(若业务需要)。

内容的提问来源于stack exchange,提问作者Emilio Anastacio

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 00:30:00