티스토리 뷰
[kotlin/jackson] enum serialization&deserialization하기!!
pansy0319 2021. 11. 6. 18:33json이란,, ㅠㅠ
json 형태로 외부 api와 데이터를 주고 받아야하는데 주고 받는 데이터 중에 enum으로 관리하고 싶은게 있었다
enum으로 관리를 하는데 외부에서 String로 데이터를 넘겨주면 deserialization할 때 enum으로 바꾸고
외부로 api를 날릴 때 enum을 String으로 넘기게 하고 싶었다!!
코틀린 어렵다 어려워!!!!!!!!!!!!!
enum class HTTPStatusCode {
OK,
NOT_FOUND,
INTERNAL_SERVER_ERROR
}
data class Response(
val status: HTTPStatusCode
)
이렇게 생긴 enum class와 data class가 있다고 하자
"{"status":"200"}"이라는 json 문자열을 Response(HTTPStatusCode.OK)처럼 serialization을 하려면
enum class HTTPStatusCode(@JsonValue val code: String) {
OK("200"),
NOT_FOUND("404"),
INTERNAL_SERVER_ERROR("500")
;
companion object {
@JvmStatic
@JsonCreator
fun set(code: String) = values().find { it.code == code }
}
}
data class Response @JsonCreator constructor(
@JsonProperty("status") val status: HTTPStatusCode
)
이렇게 하면된다!!
약간의 설명을 덧붙이자면
- @JsonValue : 해당 필드 이름을 통해 직렬화시킴
- set() 함수 : String으로 Enum 객체를 생성하는데 HTTPStatusCode("200")처럼 하는게 막혀 있어서 HTTPStatusCode.set("200")으로 만들 수가 있다
- @JsonCreator : 역직렬화할 때 set()으로 값을 세팅하라고도 알려준다
- ~ Response @JsonCreator constructor(...
- deserialization을 하려면 빈 생성자가 필요한데 해당 어노테이션을 통해 빈 생성자를 만들지 않아도 된다
- @JsonCreator 없이 하려면 Response 클래스에 매개변수가 없는 부생성자(constructor())를 추가해줘야 한다
- ex) constructor(): this(HTTPStatusCode.OK)
- @JsonProperty: deserialization할 때 어떤 필드에 매핑해야할지 알려준다(key값이랑 필드 이름이랑 동일해도 지정해줘야되더라,,,) 없으니 에러나더라,,
(틀렸을 수도 있다.. 지적 환영)
테스트를 해보자
@Test
fun `enum test`() {
// given
val objectMapper = ObjectMapper()
val jsonString = "{\"status\":\"200\"}"
val response = Response(HTTPStatusCode.OK)
// when
val deserializedObject = objectMapper.readValue(jsonString, Response::class.java).also { println("de $it") }
val serializedJsson = objectMapper.writeValueAsString(response).also { println("se $it")}
// then
assertEquals(response, deserializedObject) // 통과
assertEquals(jsonString, serializedJsson) // 통과
}
/* 실행 결과
de Response(status=OK)
se {"status":"200"}
*/
+) 추가적으로 enum class에 정의한 companion obejct의 set()함수에 대해서 이야기해보자면
없어도 serialization/deserialization하는데 문제는 없다!
근데 저게 있고 없고의 차이는 enum에서 지정하지 않은 값이 들어왔을 때
Response class에서 status를 non-null로 했는지, nullable로 했는지에 따라 달라진다
- enum에 정의된 범위를 벗어난 변수를 가진 json string을 deserialization했을 때
- set() 함수가 있을 때
- enum 변수를 non-null로 가지고 있으면 ValueInstantiationException이 발생
- enum 변수를 nullable로 가지고 있으면 null로 채워짐
- set() 함수가 없을 때
- enum 변수가 nullable, non-null에 관계 없이 InvalidFormatException이 발생함
- set() 함수가 있을 때
대충 요런 차이가 있고 enum 범위를 벗어난 값이 들어올 때 처리를 어떻게 하고 싶은지에 따라 취향껏 하면 된다~.~
enum이란,, Json이란,, 어렵다
이외에도 어떻게 세팅해야할까 이런저런 논의들이 오갔는데 데이터 담는 객체 하나 만들기 쉽지 않다는 생각을 했다...
역시 개발은 어렵다....
'📖✏️✏️✏️📝 > kotlin' 카테고리의 다른 글
[kotlin] map으로 data class list끼리 서로 변환 (0) | 2022.04.23 |
---|
- Total
- Today
- Yesterday
- docker
- java
- gradle
- 코틀린
- kotlin In Action
- ImagePullBackOff
- 자바스크립트
- 스프링부트
- Spring
- clean code
- 자바
- 도커
- gasmask
- cacheable
- docker for mac
- docker pull limit
- back merge
- kotlin
- 스프링
- linuxkit
- ddd
- springboot
- 도메인주도설계
- k8s
- QuickTimePlayer
- JavaScript
- 클린코드
- Kubernetes
- 쿠버네티스
- IntelliJ
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |