티스토리 뷰

반응형

json이란,, ㅠㅠ

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이 발생함

대충 요런 차이가 있고 enum 범위를 벗어난 값이 들어올 때 처리를 어떻게 하고 싶은지에 따라 취향껏 하면 된다~.~

 

 

enum이란,, Json이란,, 어렵다

이외에도 어떻게 세팅해야할까 이런저런 논의들이 오갔는데 데이터 담는 객체 하나 만들기 쉽지 않다는 생각을 했다...

역시 개발은 어렵다....

반응형
댓글
반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
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
글 보관함