본문 바로가기
Java & 스프링/Java

[jackson, issue] 이슈 해결 - No serializer found for class

by hjhello423 2019. 12. 28.

어떤 이슈?

급하게 테스트해볼 이슈가 있어서 간단하게 객체를 만들고 이 객체를 json string으로 변환해야 할 일이 있었습니다.

 

그래서 테스트용 class를 생성하고 이를 ObjectMapper의 writeValueAsString()를 이용하여 출력해 보았는데...

아래와 같은 에러가 튀어나왔죠.

com.fasterxml.jackson.databind.exc.InvalidDefinitionException: No serializer found for class com.hongjun423.toy_project.domain.Student and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS)

 

serializer 하는 과정에서 기본으로 접근 제한자가 public 이거나 getter/setter를 이용하기 때문에 인스턴스 필드를 private 등으로 선언하면 json으로 변환 과정에서 에러가 발생합니다.

 


해결

No serializer found for class 에러를 해결하려면 여러 가지 방법이 있는데요. 순서대로 해결방법을 알아보겠습니다.

 

첫 번째 방법은 ObjectMapper의 인스턴스에 세팅하여 private 필드로 접근 가능하도록 하는 것입니다.

아래와 같이 필드로 접근하고 접근 제한자 범위를 ANY로 설정해 주면 이 문제를 해결할 수 있습니다.

ObjectMapper mapper = new ObjectMapper();
mapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY);

 

두 번째와 세 번째 방법은 json으로 변환할 class에 어노테이션을 이용해 접근 방법을 지정하는 것입니다.

두 번째 방법은 json으로 변환할 인스턴스 필드에 @JsonProperty를 필드에 선언해주는 것입니다..

아래와 같이 @JsonProperty를 필드에 적용시키면 해당 필드는 필드의 이름값을 json의 key로 이용하게 됩니다.

@JsonProperty("addr")와 같이 선언할 경우 key로 "addr"을 사용한다는 의미입니다.

 

이 방법을 이용할 때 한 가지 주의할 점은 json으로 변환을 원하지 않는 필드에는 @JsonIgnore을 선언해 주어야 하는 부분입니다.

public class Student {
    @JsonProperty
    private String name;
    @JsonProperty
    private int age;
    @JsonProperty("addr")
    private String address;

    public Student() {
    }
}

 

세 번째 방법은 class에 @JsonAutoDetect를 선언하여 private 필드에도 접근 가능하도록 지정하는 것입니다.

아래와 같이 JsonAutoDetect.Visibility.ANY로 지정하면 private 필드에도 접근하여 json으로 변환하는 데 사용하게 됩니다. ANY 외에도 DEFAULT, NON_PRIVATE, NONE, PROTECTED_AND_PUBLIC, PUBLIC_ONLY로 지정 가능합니다.

@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY)
public class Student {
    private String name;
    private int age;
    private String address;

    public Student() {
    }
}

위 방법들의 우선순위는?

위의 세 가지 방법을 같이 사용하게 되면 우선순위대로 적용 되게 됩니다.

우선순위는 아래의 순서대로 우선 적용됩니다.

1. @JsonProperty를 이용한 필드에 선언

2. @JsonAutoDetect를 이용한 class에 선언

3. setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY)를 이용한 ObjectMapper 인스턴스에 세팅


참조

https://stackoverflow.com/questions/8367312/serializing-with-jackson-json-getting-no-serializer-found

https://alwayspr.tistory.com/31

https://dumdildor.tistory.com/13

 

 

 

 

 

 

반응형

댓글