-
Enum 유효성 검사하기Spring 2021. 8. 23. 22:58
요약
- @Pattern과 enum은 같이 쓸 수 없다.
- 커스텀어노테이션을 만들어서 @JsonCreator와 같이 사용해서 처리했다.파라미터 검증중 @Valid + @Pattern 이용해서 enum을 검증하려고 했다.
예를들어 Y,N만 들어가는 enum 타입의 멤버필드에 A를 집어 넣으려고한다면???
물론 데이터가 들어가진 않겠지만 에러코드가 상당히 이쁘지 않을 것이다.
아래 코드를 통해 처리했다.
DTO
import com.example.test.test.constant.YnCode; import javax.validation.constraints.Pattern; import lombok.Getter; import lombok.ToString; @Getter @ToString public class EnumRequestDto { private String name ; @Pattern(regexp = "Y|N") // 작동할까? private YnCode ynCode; }
enum
public enum YnCode { Y("Y"), N("N"), ; private final String code; YnCode(String code) { this.code = code; } public String getCode() { return code; } }
controller
@PostMapping("/yncode") public String insertYnCode(@RequestBody @Valid EnumRequestDto enumRequestDto) { log.info("insertYnCode param : {}", enumRequestDto); return "OK"; }
test
json parse error! 발생
Resolved [org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Cannot deserialize value of type `com.example.test.test.constant.YnCode` from String "ABC": not one of the values accepted for Enum class: [NONE, Y, N]; nested exception is com.fasterxml.jackson.databind.exc.InvalidFormatException: Cannot deserialize value of type `com.example.test.test.constant.YnCode` from String "ABC": not one of the values accepted for Enum class: [Y, N]
enum을 검증하려면 커스텀어노테이션을 만들어야 한다...
커스텀 어노테이션 만들기
import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import javax.validation.Constraint; import javax.validation.Payload; @Constraint(validatedBy = EnumPatternValidator.class) @Target({ElementType.FIELD}) @Retention(RetentionPolicy.RUNTIME) public @interface EnumPattern { String regexp(); String message() default "does not match \"{regexp}\""; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; }
import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.regex.PatternSyntaxException; import javax.validation.ConstraintValidator; import javax.validation.ConstraintValidatorContext; public class EnumPatternValidator implements ConstraintValidator<EnumPattern, Enum<?>> { private Pattern pattern; @Override public void initialize(EnumPattern annotation) { try { pattern = Pattern.compile(annotation.regexp()); } catch (PatternSyntaxException e) { throw new IllegalArgumentException("pattern regex is invalid", e); } } @Override public boolean isValid(Enum<?> value, ConstraintValidatorContext context) { if (value == null) { return false; } Matcher m = pattern.matcher(value.name()); return m.matches(); } }
자이제 적용해 보자.
@EnumPattern(regexp = "Y|N", message = "Y 또는 N만 입력 가능합니다") private YnCode ynCode;
띠롱. JSON parse error 발생..
왜냐하면 애당초 enum에 정해진 값외 들어와 버리면 JSON parse error가 난다.
그럼 어떻게 해야할까?
@JsonCreator를 이용했다.
이걸 사용하면 하면 JSON 객체를 deserialize해서 객체맵핑시 사용할 생성자를 지정할 수 있게 해준다.
파라미터로 Y,N값이외의 값이 들어오면 null을 전달하게하였다.
그러면 EnumPatternValidator에 NONE이 전달되고 Pattern class를 통해서 일치여부를 검증한다.
import com.fasterxml.jackson.annotation.JsonCreator; import java.util.stream.Stream; public enum YnCode { Y("Y"), N("N") ; private final String code; YnCode(String code) { this.code = code; } public String getCode() { return code; } @JsonCreator(mode = JsonCreator.Mode.DELEGATING) public static YnCode findByCode(String code) { return Stream.of(YnCode.values()) .filter(c -> c.code.equals(code)) .findFirst() .orElse(null); } }
아주 친근한 exeption이 발생했다. MethodArgumentNotValidException ^^
이제 에러 메세지를 이쁘게 가공해서 내려주면 끝.
참고로
@JsonCreator와 @Pattern만 사용해도 작동하지 않을까? 생각이들었지만 enum + @Pattern은 작동하지 않는다.
validation.UnexpectedTypeException 발생
javax.validation.UnexpectedTypeException: HV000030: No validator could be found for constraint 'javax.validation.constraints.Pattern' validating type 'com.example.test.test.constant.YnCode'. Check configuration for 'ynCode'
다른 방법이 있다면 공유부탁드리겠습니다^^ ㅎㅎ
'Spring' 카테고리의 다른 글
Spring Cloud Config 설정값 변경 후 반영하는 방법 (0) 2021.06.03 myBatis LocalDate , LocalDatetime 바인딩하는 법 (0) 2020.11.15 spring batch 링크모음 (0) 2020.04.21 Gradle 인식못할 때 (0) 2020.04.02 @Valid 와 @ControllerAdvice로 DTO 예외처리하기 (3) 2020.01.12