Java

RequestBody를 Enum 값에 Setting 할 때 생기는 문제

체리필터 2019. 11. 13. 16:56
728x90
반응형

아래와 같은 Enum 이 있다.

public enum InterestGoodsCategoryType {
    MOTEL("MOTEL"),
    HOTEL("HOTEL"),
    PENSION("PENSION"),
    GUESTHOUSE("GUESTHOUSE"),
    ACTIVITY("ACTIVITY");

    String typeCode;
    private static List<InterestGoodsCategoryType> allList;

    InterestGoodsCategoryType(String typeCode) {
        this.typeCode = typeCode;
    }

    public String getCode() {
        return this.typeCode;
    }

    @JsonValue
    public InterestGoodsCategoryType jsonValue() {
        return this.typeCode;
    }

    public static InterestGoodsCategoryType fromValue(String value) {
        switch (value) {
            case "MOTEL":
                return InterestGoodsCategoryType.MOTEL;
            case "HOTEL":
                return InterestGoodsCategoryType.HOTEL;
            case "PENSION":
                return InterestGoodsCategoryType.PENSION;
            case "GUESTHOUSE":
                return InterestGoodsCategoryType.GUESTHOUSE;
            case "ACTIVITY":
                return InterestGoodsCategoryType.ACTIVITY;
        }
        return null;
    }

    public static List<InterestGoodsCategoryType> getAll() {
        if (Objects.isNull(allList)) {
            allList = new ArrayList<>(
                    Arrays.asList(MOTEL, HOTEL, PENSION, GUESTHOUSE, ACTIVITY)
            );
        }

        return allList;
    }
}

이럴 경우 Response에서 해당 Enum을 반환하면 typeCode 즉 MOTEL, HOTEL 등등의 코드 값이 리턴된다.

클라이언트의 요구 사항이 각 코드 값에 맞는 한글 이름을 반환해 달라고 해서 구조를 살짝 바꾸었다.

 

public enum InterestGoodsCategoryType {
    MOTEL("MOTEL", "모텔"),
    HOTEL("HOTEL", "호텔"),
    PENSION("PENSION", "펜션"),
    GUESTHOUSE("GUESTHOUSE", "게스트\n하우스"),
    ACTIVITY("ACTIVITY", "엑티\n비티");

    String typeCode;
    String typeName;
    private static List<InterestGoodsCategoryType> allList;

    InterestGoodsCategoryType(String typeCode, String typeName) {
        this.typeCode = typeCode;
        this.typeName = typeName;
    }

    public String getCode() {
        return this.typeCode;
    }

    public String getName() {
        return this.typeName;
    }

    @JsonValue
    public InterestGoodsCategoryTypeDto jsonValue() {
        return InterestGoodsCategoryTypeDto.builder().category(this.typeCode).name(this.typeName).build();
    }

    public static InterestGoodsCategoryType fromValue(String value) {
        switch (value) {
            case "MOTEL":
                return InterestGoodsCategoryType.MOTEL;
            case "HOTEL":
                return InterestGoodsCategoryType.HOTEL;
            case "PENSION":
                return InterestGoodsCategoryType.PENSION;
            case "GUESTHOUSE":
                return InterestGoodsCategoryType.GUESTHOUSE;
            case "ACTIVITY":
                return InterestGoodsCategoryType.ACTIVITY;
        }
        return null;
    }

    public static List<InterestGoodsCategoryType> getAll() {
        if (Objects.isNull(allList)) {
            allList = new ArrayList<>(
                    Arrays.asList(MOTEL, HOTEL, PENSION, GUESTHOUSE, ACTIVITY)
            );
        }

        return allList;
    }
}
@Builder
@Getter
public class InterestGoodsCategoryTypeDto {
    private String category;
    private String name;
}

 

typeCode에 더불어 typeName 이란 것을 추가 하였고, 생성자에서 이름을 받아 들이도록 수정하였다.

그리고 @JsonValue 어노테이션이 붙은 메소드에서는 별도의 DTO 객체를 통해서 구조화 되어 내려가도록 만들었다.

이렇게 만들 경우 json response는 아래와 같은 모습으로 나오게 된다.

{
    "data": [
        {
            "category": "MOTEL",
            "name": "모텔"
        },
        {
            "category": "HOTEL",
            "name": "호텔"
        },
        {
            "category": "PENSION",
            "name": "펜션"
        },
        {
            "category": "GUESTHOUSE",
            "name": "게스트\n하우스"
        },
        {
            "category": "ACTIVITY",
            "name": "엑티\n비티"
        }
    ]
}

 

하지만 RequestBody로 값이 넘어오는 경우 해당 Enum에 값을 맵핑해 주지 못하는 경우가 발생한다.

이럴 경우 어떻게 해야 하는지 고민을 하고 검색도 했는데 들인 시간에 비해 해결 방법은 너무 간단하였다.

Setter를 변형 해야 할 거라고 생각 하였지만 단 1개의 어노테이션을 붙여주면 되었다.

 

public enum InterestGoodsCategoryType {
    MOTEL("MOTEL", "모텔"),
    HOTEL("HOTEL", "호텔"),
    PENSION("PENSION", "펜션"),
    GUESTHOUSE("GUESTHOUSE", "게스트\n하우스"),
    ACTIVITY("ACTIVITY", "엑티\n비티");

    String typeCode;
    String typeName;
    private static List<InterestGoodsCategoryType> allList;

    InterestGoodsCategoryType(String typeCode, String typeName) {
        this.typeCode = typeCode;
        this.typeName = typeName;
    }

    public String getCode() {
        return this.typeCode;
    }

    public String getName() {
        return this.typeName;
    }

    @JsonValue
    public InterestGoodsCategoryTypeDto jsonValue() {
        return InterestGoodsCategoryTypeDto.builder().category(this.typeCode).name(this.typeName).build();
    }

    @JsonCreator
    public static InterestGoodsCategoryType fromValue(String value) {
        switch (value) {
            case "MOTEL":
                return InterestGoodsCategoryType.MOTEL;
            case "HOTEL":
                return InterestGoodsCategoryType.HOTEL;
            case "PENSION":
                return InterestGoodsCategoryType.PENSION;
            case "GUESTHOUSE":
                return InterestGoodsCategoryType.GUESTHOUSE;
            case "ACTIVITY":
                return InterestGoodsCategoryType.ACTIVITY;
        }
        return null;
    }

    public static List<InterestGoodsCategoryType> getAll() {
        if (Objects.isNull(allList)) {
            allList = new ArrayList<>(
                    Arrays.asList(MOTEL, HOTEL, PENSION, GUESTHOUSE, ACTIVITY)
            );
        }

        return allList;
    }
}

그렇다. @JsonCreator 어노테이션을 붙여 주면 된다.

넘어오는 RequestBody의 모습은 아래와 같다.

{
	"birthMonth" : "2019-11",
    "interestGoodsCategoryTypeList" : ["HOTEL", "PENSION"]
}

HOTEL, PENSION 과 같은 코드 값만 넘오 오더라도 해당 값을 @JsonCreator 어노테이션을 달은 메소드에서 맵핑해서 실제 Enum을 리턴해 주도록 만들면 된다.

 

오늘의 삽질은 여기까지...

728x90
반응형