简体   繁体   中英

How to turn off deserialization for enum

I would like to turn off deserialization for concrete enum. Is it possible?

Exercise model class:

package main.exercise;

import lombok.*;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;

@AllArgsConstructor
@NoArgsConstructor
@Getter
@Entity
@Builder
public class Exercise {

    @Id
    @GeneratedValue
    private int id;
    @NonNull
    private String name;
    @NonNull
    private ExerciseType exerciseType;
    private double caloriesBurned;
    private String exerciseDescription;
}

I got method in controller:

@PostMapping("/addExercise")
public List<String> addExercise(@RequestBody Exercise exercise) {
    return exerciseCrudActivitiesService.addExercise(exercise);
}

which takes Exercise body and if type of Exercise is wrong I got error while POST http request:

Resolved [org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Cannot deserialize value of type `main.exercise.ExerciseType` from String "CARdDIO": not one of the values accepted for Enum class: [CARDIO, WEIGHTLIFTING]; nested exception is com.fasterxml.jackson.databind.exc.InvalidFormatException: Cannot deserialize value of type `main.exercise.ExerciseType` from String "CARdDIO": not one of the values accepted for Enum class: [CARDIO, WEIGHTLIFTING]
 at [Source: (PushbackInputStream); line: 4, column: 25] (through reference chain: main.exercise.Exercise["exerciseType"])]

The point is in service I got validator, which validates whether type of enum is right or wrong and return string to list of errors from all validators. Unfortunately this code cannot be reached because of error.

public List<String> addExercise(Exercise exercise) {
        ExerciseValidator validator = new ExerciseValidator();
        List<String> messages = validator.validate(exercise);
        if (messages.isEmpty()) {
            exerciseRepository.save(exercise);
        }
        return messages;
    }

Validator

package main.exercise.validator.attributesvalidators;

import main.exercise.Exercise;
import main.exercise.ExerciseType;
import main.exercise.validator.ExerciseAttributesValidator;

import java.util.InputMismatchException;

public class ExerciseTypeValidator implements ExerciseAttributesValidator {

    @Override
    public String validate(Exercise exercise) {
        if (exercise.getExerciseType() == null) {
            return "You didn't put exercise type!";
        }
        try {
            ExerciseType.forName(exercise.getExerciseType().name());
        } catch (InputMismatchException e) {
            return "Wrong exercise type!";
        }

        return null;
    }
}

To turn off (de-)serialization, you can add the @JsonIgnore to the exerciseType field. However, I don't think this will help you anyways.

If serialization is ignored, the field would always be null which is not the intended behavior.

Your validator is too late. Note: the validate method takes an Exercise object as a parameter. The problem occurs during the creation of this object already. When you get to the point that the line ExerciseType.forName(exercise.getExerciseType().name()); get's executed, it will NEVER throw an exception, because getExerciseType() is already a valid enum.

Instead of this custom validator, you could make use of a Spring @ControllerAdvice to register your own Exception handler for that error type.

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.context.request.WebRequest;
import com.fasterxml.jackson.databind.exc.InvalidFormatException

@ControllerAdvice
public class GlobalExceptionHandler {
    @ExceptionHandler(InvalidFormatException.class)
    public ResponseEntity<?> badFormatException(InvalidFormatException ex, WebRequest request) {
        ErrorDetails errorDetails = new ErrorDetails(new Date(), ex.getMessage(), request.getDescription(false));
        return new ResponseEntity<>(errorDetails, HttpStatus.BAD_REQUEST);
    }
}

See eg https://www.springboottutorial.com/spring-boot-exception-handling-for-rest-services for more details.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM