@JsonCreater : Enum Type Request DTO Mapping
Enum type을 쓰다보면 별칭을 주는 경우들이 있습니다. 이렇게 별칭을 줘서 사용할 경우 Enum Type의 Request DTO에 Request body가 매핑되는 과정에서 매핑오류가 나는 경우가 생깁니다.
아래는 카테고리를 관리하는 Enum입니다. 각각의 Enum에는 프론트엔드에 보여지는 이름인 viewName을 별칭으로 주었습니다.
@Getter
@AllArgsConstructor
public enum TagCategory {
// 일상
HOBBY("취미"),
LIFEHACK("꿀팁"),
// 동물
DOG("개"),
CAT("고양이"),
REPTILE("파충류"),
INSECT("곤충"),
private String viewName;
}
아래는 폴더를 생성하는 RequestDTO입니다. 여기에는 폴더가 갖게될 태그들도 입력할 수 있게 되어있습니다. 문제는 이때 request body로 { tags : ["취미", "개"]}
가 들어오면 "취미", "개"와 일치하는 Enum이 존재하지 않는다
는 에러가 납니다. 즉 매핑이 제대로 되지 않고 있는 것입니다.
이때 { tags : ["HOBBY", "DOG"] }
라고 입력이 들어오면 매핑이 잘 됩니다.
-> 여기서 우리는 새로만들어준 ✨viewName을 어떻게 매핑해야할지 ✨ 모르기때문에 생기는 문제라는 것을 알 수 있습니다. 그리고 이는 jackson과 큰 연관이 있습니다.
public class CreateFolderRequest {
@NotBlank(message = "폴더의 이름을 입력해주세요")
private String title;
@NotBlank(message = "폴더의 이미지를 설정해주세요")
private String image;
@NotNull(message = "폴더의 내용을 입력해주세요")
private String content;
private Long originId;
@NotNull(message = "폴더 고정여부를 설정해주세요")
private Boolean isPinned;
@NotNull(message = "폴더 공개여부를 설정해주세요")
private Boolean isPrivate;
private List<TagCategory> tags;
private List<BookmarkRequest> bookmarks;
...
}
이 문제는 Jackson Annotation중 @JsonCreater
를 사용해 매핑함수를 만들어주면 해결할 수 있습니다. 이렇게하면 request body로 들어온 String값 sub와 viewName들중 일치하는 TagCategory객체를 반환해주기때문에 그것으로 매핑합니다. 없다면 null을 반환해주고 이때는 정말 우리가 의도한 매핑에러가 나게됩니다.
public enum TagCategory {
...
@JsonCreator
public static TagCategory from(String sub) {
for (TagCategory tag : TagCategory.values()) {
if (tag.getViewName().equals(sub)) {
return tag;
}
}
return null;
}
}
이 외에도 request body의 변수명이 DTO에서 매핑되는 변수와 다를때도 @JsonCreater로 역직렬화 과정에 개입해 의도한대로 매핑되도록 해줄 수 도있습니다. 이외에도 다양한 Jackson Annotation을 이용해 직렬화, 역직렬화 과정에서의 불편함을 해소할 수 있습니다.
글 잘 읽었습니다. 감사합니다.