Programing/Error Resolution(오류해결)

exception is org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Cannot deserialize value of type 오류 해결하기.

세기루민 2023. 4. 24. 08:38
728x90

안녕하세요 세기무민입니다.

이번 포스팅은 실무에서 역직렬화 관련하여 발생한 오류 해결과 관련하여 포스팅 해보려고 합니다.

실제 현업에서 사용하는 코드는 사용하지 못하기 때문에 예시 코드와 예시 내용으로 작성되는 포스팅입니다.

 

1. 문제 상황 설명 및 원인 파악

현재 제가 개발하고 있는 A라는 서비스에서 B라는 서비스를 호출하여 특정 맴버 값을 받아와야 하는 API라고 가정합시다. 

// A가 B에게 전달하려는 API Reqeust 
{
    memberSeq : Int,
    memberName : String,
    memberType : String
}

// A가 B에게 전달받은 API Response 값
{
    // Int
    memberSeq : 100112,
    // String
    memberName : "sg-moomin"
    // Enum
    memberType : 0
}

위의 내용은 예시이며 유사한 상황을 재현하려고 합니다.

저는 전달값은 Object -> Json 형태로 담아서 전달하였고 B라는 서비스에서는 Json 형태로 전달해주었습니다.

이때 제가 Json 형태로 들어온 값에 대해 객체와 일치하는 경우라면 역직렬화 문제가 발생하지 않지만 

두개의 값이 다를 경우 역직렬화 오류가 발생하게 됩니다.

 

저의 memberTypeCode와 DTO는 아래와 같았습니다. 

/*
 * memberTypeCode(Enum)
 */

public enum MemberTypeCode {
    OWNER(0, "대표"),
    MANAGER(1, "관리"),
    COMMON(2, "일반"),
    NEW(3, "신규회원")
    
    final private String code;
    final private String comment;
    
    
    MemberTypeCode(String code, String comment){
    	this.code = code;
        this.comment = comment;
    }
}

/*
 * memberResDto
 */
 
 @Getter
 @ToString
 public class MemberResDto {
   private int memberSeq;
   private String memberName;
   private MemberTypeCode memberType;
 }

즉 B서비스에서 저에게 Response를 전달해줄 때 Enum값이 아닌 Enum의 필드(code, comment) 값으로 전달해주는 경우

Json Key값과 일치하지 않음으로 맵핑 생성자를 지정할 수 없어서 위와 같은 오류가 발생한다.

2. 문제 해결

해결 방법은  @JsonCreator를 이용하는 방법이다. 

@JsonCreator를 이용하면 역직렬화 시 맵핑 생성자 지정을 도와주기 떄문에 필드 값으로 전달해주더라도 작동에 

문제가 없다. 

@JsonCreator를 사용하는 코드는 아래와 같다.

/*
 * memberTypeCode(Enum)
 */

public enum MemberTypeCode {
    OWNER(0, "대표"),
    MANAGER(1, "관리"),
    COMMON(2, "일반"),
    NEW(3, "신규회원")
    
    final private String code;
    final private String comment;
    
    
    MemberTypeCode(String code, String comment){
    	this.code = code;
        this.comment = comment;
    }
    
    @JsonCreator
    public static MemberTypeCode deserializeOfmemberType(String memberType){
    	for(MemberTypeCode memberTypeCode : value()){
        	if(memberTypeCode.getCode() == memberType || memberTypeCode.getComment.equals(memberType)){
            	return memberTypeCode;
            }
        }
        return null;
    }
}

/*
 * memberResDto
 */
 
 @Getter
 @ToString
 public class MemberResDto {
   private int memberSeq;
   private String memberName;
   private MemberTypeCode memberType;
   
   @JsonGetter("memberType")
   private String getMemberTypeComment(){
   	if(memberType != null){
    	return memberType.getComment();
    } 
    return null;    
   }
 }

@JsonCreator를 이용하여 필드값으로 들어오는 케이스에 대해 맵핑 생성자를 생성해준다. 

조건문은 response로 전달해주는 서비스와 협의에 따라 간소화 가능하고 예시처럼 모든 필드를 필수로 검토할 필요는 없다.

또한 @JsonCreator를 이용하더라도 Front로 넘겨주는 값을 Enum값 그대로 넘겨주는 거라면 문제가 없지만 

필드 값에 대해서 필요 시에는 @JsonGetter를 이용하여 원하는 필드 값을 반환해주면 된다.

3. 마무리

이번 포스팅에서는 Json값으로 전달 받을 떄 @JsonCreator를 이용하여 Json 객체를 역직렬화하여 맵핑 생성자를

생성해주지 않을 경우 위와 같은 오류가 발생한 다는 것을 확인해봤습니다.

다음 포스팅에서는 더 유익한 정보로 찾아오겠습니다. 

728x90