본문 바로가기
Spring

Spring Validation 특정 String만 받도록 검증 하기

by wadekang 2023. 11. 9.

Request 시 String 필드가 특정 String만 받도록 검증하려고 할 때 다음과 같이 구현

 

@EnumValidator라는 Custom Annotation을 만들어서 target Enum에서 정의한 값들만 해당 필드에 받을 수 있도록 검증

 

EnumValidator (Annotation)

@Documented  
@Constraint(validatedBy = EnumValidatorImpl.class)  
@Retention(RetentionPolicy.RUNTIME)  
@Target(ElementType.FIELD)  
@NotNull(message = "Value cannot be null")  
@ReportAsSingleViolation  
public @interface EnumValidator {  
  
    Class<? extends Enum<?>> targetEnum();  
  
    String message() default "Value is not valid";  
  
    Class<?>[] groups() default {};  
  
    Class<? extends Payload>[] payload() default {};  
  
}

 

EnumValidatorImpl

public class EnumValidatorImpl implements ConstraintValidator<EnumValidator, String> {  
  
    Set<String> valueSet = null;  
  
    @Override  
    public boolean isValid(String value, ConstraintValidatorContext context) {  
        return valueSet.contains(value.toUpperCase());  
    }  
  
    @Override  
    public void initialize(EnumValidator constraintAnnotation) {  
        valueSet = new HashSet<>();  
        Class<? extends Enum<?>> enumClass = constraintAnnotation.targetEnum();  
  
        @SuppressWarnings("rawtypes")  
        Enum[] enumValArr = enumClass.getEnumConstants();  
  
        for (@SuppressWarnings("rawtypes") Enum enumVal : enumValArr) {  
            valueSet.add(enumVal.toString().toUpperCase());  
        }  
    }  
}

 

Request VO에 @EnumValidator 적용

1. Target Enum 정의

public enum AuthGroup {  
    ADMIN,  
    USER  
}

 

2. VO에 적용

@Data  
public class TestVO {  
  
    private String name;  
    private int age;  
  
    @EnumValidator(  
            targetEnum = AuthGroup.class, 
            message = "authGroup can be either ADMIN or USER"  
    )  
    private String authGroup;  
  
}

 

Test

- @Validated annotation 적용

@PostMapping("/test")  
public CommonResponse<TestVO> test(@RequestBody @Validated TestVO vo) {
  ...
}

 

- Request (IntelliJ Http Reqeust 사용함)

###  
//@no-log  
POST http://localhost:5423/test  
Content-Type: application/json  
  
{  
    "name": "name",    
    "age": 27,    
    "authGroup": "GUEST"
}

// Response
{
  "timestamp": "2023-11-09T05:02:17.477+00:00",
  "status": 400,
  "error": "Bad Request",
  "path": "/test"
}

 

- Error Log

2023-11-09 14:02:17.477  WARN 18195 --- [nio-5423-exec-7] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.web.bind.MethodArgumentNotValidException: Validation failed for argument [0] in public com.example.demo.vo.CommonResponse<com.example.demo.vo.TestVO> com.example.demo.ctl.DemoController.test(com.example.demo.vo.TestVO): [Field error in object 'testVO' on field 'authGroup': rejected value [GUEST]; codes [EnumValidator.testVO.authGroup,EnumValidator.authGroup,EnumValidator.java.lang.String,EnumValidator]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [testVO.authGroup,authGroup]; arguments []; default message [authGroup],class com.example.demo.validation.AuthGroup]; default message [authGroup can be either ADMIN or USER]] ]

 

@EnumValidator에서 입력한 message가 default message에 출력되는 것 확인

 


참고

Java String validation using enum values and annotation
 

Java String validation using enum values and annotation

I want to validate a string against a set of values using annotations. What I want is basically this: @ValidateString(enumClass=com.co.enum) String dataType; int maxValue; int minValue; int prec...

stackoverflow.com

 

 

댓글