Json 객체에서 is prefix가 사라지는 문제

신연우·2024년 12월 28일

WIL

목록 보기
18/21

문제 상황

data class SmsSendRequest(
    val phoneNumber: String,
    val smsTitle: String,
    val content: String,
    val isAuthMessage: Boolean,
)

위와 같은 data class 객체를 kafka queue에 넣었습니다. 그리고 컨슈머에서는 isAuthMessage 값이 true일 때는 인증용 메시지 전용 로직을 태우는 코드가 작성되어 있습니다.

isAuthMessage 값을 true로 해서 kakfa로 메시지를 발행했지만 인증용 메시지 전용 로직을 타지 못하는 것을 확인했습니다. kafka queue에 들어간 메시지를 확인해보니 아래와 같이 'is' prefix 값이 사라진채로 들어간 것을 확인했습니다.

{
  "phoneNumber": "01011111111",
  "smsTitle": "로그인 인증번호",
  "content": "인증번호는 [1111111]입니다.",
  "authMessage": true
}

원인

How Jackson ObjectMapper Matches JSON Fields to Java Fields
To read Java objects from JSON with Jackson properly, it is important to know how Jackson maps the fields of a JSON object to the fields of a Java object, so I will explain how Jackson does that.

By default Jackson maps the fields of a JSON object to fields in a Java object by matching the names of the JSON field to the getter and setter methods in the Java object. Jackson removes the "get" and "set" part of the names of the getter and setter methods, and converts the first character of the remaining name to lowercase.

For instance, the JSON field named brand matches the Java getter and setter methods called getBrand() and setBrand(). The JSON field named engineNumber would match the getter and setter named getEngineNumber() and setEngineNumber().

출처 : jenkov.com

Spring에서 사용하는 기본 ObjectMapper인 JacksonObjectMapper의 경우 Json 객체의 필드명을 getter, setter 메서드와 일치시킵니다. 이때 getter와 setter에서 각각 "get", "set" prefix를 제거해서 필드명을 추출합니다.

In addition, for boolean properties, we allow a getter method to match the pattern:

public boolean is<PropertyName>();

This "isPropertyName" method may be provided instead of a "get<PropertyName>" method, or it may be provided in addition to a "get<PropertyName>" method. In either case, if the is<PropertyName> method is present for a boolean property then we will use the "is<PropertyName>" method to read the property value. An example boolean property might be:

public boolean isMarsupial(); public void setMarsupial(boolean m);

출처 : JavaBeans Specification

Boolean의 경우 getter의 prefix가 "get"이 아닌 "is"로 설정되기 때문에 jacksonObjectMapper에서도 "is" prefix를 제거하는 형태로 동작합니다. 따라서 isAuthMessage에서 "is" prefix를 제거한 authMessage가 Json 객체의 필드명으로 설정됩니다.

해결방법

Boolean 변수명에서 "is" prefix를 제거하면 됩니다. 그러면 Json 객체에는 코드에서 명명한 필드명 그대로 들어가게 됩니다.

@field:JsonProperty("isAuthMessage")
val isAuthMessage: Boolean,

또는 JsonProperty를 사용하는 방법도 있습니다. 이를 이용하면 변수명에 "is" prefix를 붙인채로 사용할 수 있습니다.

{
  "phoneNumber": "01011111111",
  "smsTitle": "로그인 인증번호",
  "content": "인증번호는 [1111111]입니다.",
  "authMessage": true,
  "isAuthMessage": true
}

다만 위와 같이 Json 객체에 isAuthMessage 뿐 아니라 authMessage 필드도 함께 들어가게 되는 단점이 있습니다.

참고한 글

profile
남들과 함께하기 위해서는 혼자 나아갈 수 있는 힘이 있어야 한다.

0개의 댓글