2018년 3월 25일 일요일

HATEOAS 적용 후 Serializtion 시 ID Field가 사라지는 현상

Spring에서 hateoas를 사용 할 경우 serialize 대상 class에 id가 있을 때 사라지는 현상이 존재한다.

간단한 예제를 보자

import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.module.kotlin.registerKotlinModule
import org.junit.jupiter.api.Test
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder

internal class JacksonTest{

    @Test
    fun jsonTest(){

        val jackson = Jackson2ObjectMapperBuilder.json()
                .build()
                .registerKotlinModule()

        print(jackson.writeValueAsString(Test(100L,"item")))

    }
}

data class Test(
        val id:Long,
        val name:String
)

result: {"id":100,"name":"item"}



현재는 정상이다. 여기에 ResourceSupport를 extend 해보자.


data class Test(
        val id:Long,
        val name:String
): ResourceSupport()


result: {"name":"item","links":[]}

id값이 출력되지 않는 현상이 생긴다.

결론부터 말하면 ResourceSupport엔에 코드를 보면 getId를 Ignore한다.

public class ResourceSupport implements Identifiable {

 private final List links;

 public ResourceSupport() {
  this.links = new ArrayList();
 }

 /**
  * Returns the {@link Link} with a rel of {@link Link#REL_SELF}.
  */
 @JsonIgnore
 public Link getId() {
  return getLink(Link.REL_SELF);
 }
}



이유는 요기 대충 설명이 되어있다.


이를 해결 하는 가장 쉬운 방법은 Jackson2HalModule을 추가하면 된다. 

만약 kotlin으로 개발 할 경우 에러를 낼 것이다. 

 @Test
    fun jsonTest(){

        val jackson = Jackson2ObjectMapperBuilder.json()
                .build()
                .registerKotlinModule()
                .registerModule(Jackson2HalModule())

        print(jackson.writeValueAsString(Test(100L,"item")))

    }

result: 
com.fasterxml.jackson.databind.JsonMappingException: Class org.springframework.hateoas.hal.Jackson2HalModule$HalLinkListSerializer has no default (no arg) constructor

 at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:291)



HalLinkListSerializer가 args가 없는 constructor로 선언되어 있지 않고 kotlin-noargs 라이브러리가 적용되지 않기 때문이다.

이런때는 간단히 @JsonIgnore 를 추가해주면 된다.


data class Test(
        @get:JsonIgnore(false)
        val id:Long,
        val name:String
): ResourceSupport()

result : {"id":100,"name":"item","links":[]}




댓글 없음:

댓글 쓰기