ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Spring] request에서 enum으로 값 전달받기
    Framework/Spring 2022. 3. 15. 23:27

    모든 소스 코드는 github를 통해서 확인하실 수 있습니다.

     

    Controller에서 request 값을 받을 때 보통 String값을 많이 쓴다. 그렇다면 String이 아닌 enum 값이 포함된 값은 어떻게 받을까?

    @Slf4j
    @RestController
    public class ProductController {
    
        @PostMapping("/")
        public String createProduct(@RequestBody CreateProductDto dto) {
            log.info("ProductStatus = {}", dto.getProductStatus());
            log.info("ProductName = {}", dto.getProductName());
            log.info("Count = {}", dto.getCount());
            log.info("Price = {}", dto.getPrice());
    
            return "success";
        }
    
    }
    @Data
    public class CreateProductDto {
    
        private ProductStatus productStatus;
    
        private String productName;
    
        private Integer count;
    
        private Integer price;
    
    }
    public enum ProductStatus {
        WAITING("waiting"),
        APPROVE("approve"),
        REJECT("reject");
    
        @Getter
        private final String value;
    
        ProductStatus(String value) {
            this.value = value;
        }
    
    }

     

    위와 같이 controller, dto가 정의되어 있고 dto안에 enum타입의 변수를 가지고 있다. 이 후 포스트맨에 요청을 날려보자.

    ??????

    그러면 이렇게 잘 안되는 모습을 알 수 있다. 에러를 확인해보면 다음과 같다.

     

    JSON parse error: Cannot deserialize value of type enums.ProductStatus from String "waiting": not one of the values accepted for Enum class: [WAITING, REJECT, APPROVE]; 

     

    간단히 말해서 deserialize를 할 수 없어 다음과 같은 값을 받을 수 없다는 말이다.

    값이 enum이므로 숫자로 한번 보내보면 어떨까?

    잘 되는 것을 확인할 수 있다! 그러나.. 이러한 숫자 방식은 api를 요청 보내는 쪽이나 받는 쪽이나 바람직하지 않다. 그렇다면 문자로 받기 위해서는 어떻게 해야할까?

     

    다음 소스를 enum 코드에 붙여넣으면 된다.

        @JsonCreator
        public static ProductStatus from(String value) {
            for (ProductStatus status : ProductStatus.values()) {
                if (status.getValue().equals(value)) {
                    return status;
                }
            }
            return null;
        }
        
        @JsonValue
        public String getValue() {
            return value;
        }

     

    @JsonCreator와 @JsonValue는 각각 역직렬화, 직렬화를 수행하게 된다.

     

    그런데 @JsonValue가 있는 함수를 살펴보면 단순히 선언된 value값을 가져오는 것을 알 수 있다. 이전 enum코드를 눈여겨 보면 

    private final String value라는 값을 확인할 수 있는데 lombok으로 @Getter라고 적용되어있다. 여기에 바로 JsonValue 어노테이션을 적용시키면 안되는 걸까?

        @JsonValue
        @Getter
        private final String value;

    아쉽지만 이 방식으로는 되지 않는다. 이러한 방식이 왜 안되는지는 파악하지 못했다. 그리고 또한 지금 방식은 역직렬화만 수행하면 되기에 @JsonCreator만 있으면 된다고 파악했는데 왜 @JsonValue부분까지 있어야 하는지.. 이 부분은 좀 더 연구가 필요한 듯 싶다.

    또한 이러한 어노테이션 기반 뿐 아니라 converter를 등록하여 하는 방법도 있다. (이 부분은 다음에 다시 작성해보도록 하겠다)

    'Framework > Spring' 카테고리의 다른 글

    [Spring] Test 코드에서 @Slf4j 사용하기  (0) 2022.05.03
    [Spring] Domain time mapping  (0) 2022.04.25
    [Spring] Querydsl 동적 쿼리  (0) 2022.03.04
    [Spring] QueryDsl projection(2)  (0) 2022.03.02
    [Spring] QueryDsl projection  (0) 2022.03.01
Designed by Tistory.