Jackson 을 이용하여 Json 문자열을 쓸 때, 모든 속성을 다 노출하고 싶지 않은 경우가 있다.
이럴 때 @JsonView 를 사용할 수 있다.
예제 코드를 살펴보자.
@Data
@Builder
public class Album {
private String albumId;
private String albumName;
private Singer representSinger;
private List<Track> tracks;
}
|
@Data
@Builder
public class Singer {
private String name;
private String nickname;
private String managementCompany;
}
|
@Data
@Builder
public class Track {
private String trackId;
private String trackTitle;
private String trackNo;
private String genre;
private Singer singer;
}
|
위 처럼 Album, Singer, Track 3가지 모델이 있다고 가정하자.
Album 클래스를 Json 으로 변환하면 모든 정보를 포함하게 된다. 하지만 ID 정보는 외부에 노출하고 싶지 않을 수 있다.
이 경우 어떻게 설정할 수 있을까?
public class JsonViewTest {
private static JacksonJsonParser parser;
@BeforeClass
public static void init() {
parser = new JacksonJsonParser();
}
@Test
public void nonJsonViewTest() throws Exception {
Album album = Album.builder()
.albumId("albumId")
.albumName("albumName")
.representSinger(
Singer.builder()
.name("singerName")
.nickname("singerNickname")
.managementCompany("managementCompany")
.build()
)
.tracks(
Arrays.asList(
Track.builder()
.trackId("trackId1")
.trackNo("1")
.trackTitle("No.1 Track")
.genre("genre")
.singer(
Singer.builder()
.name("singerName")
.nickname("singerNickname")
.managementCompany("managementCompany")
.build()
)
.build()
)
)
.build();
parser.printPrettyJson(album);
}
}
|
{
"albumId" : "albumId",
"albumName" : "albumName",
"representSinger" : {
"name" : "singerName",
"nickname" : "singerNickname",
"managementCompany" : "managementCompany"
},
"tracks" : [ {
"trackId" : "trackId1",
"trackTitle" : "No.1 Track",
"trackNo" : "1",
"genre" : "genre",
"singer" : {
"name" : "singerName",
"nickname" : "singerNickname",
"managementCompany" : "managementCompany"
}
} ]
}
|
Json 은 위 결과와 같이 모든 정보를 포함하게 된다.
ViewModel 을 선언한 다음 아래와 같이 @JsonView 설정을 해 보자.
public abstract class ViewModel implements Serializable {
public interface DefaultView {}
public interface SummaryView extends DefaultView {}
public interface DetailView extends SummaryView {}
}
|
@Data
@Builder
public class Album {
private String albumId;
@JsonView(ViewModel.DefaultView.class)
private String albumName;
@JsonView(ViewModel.SummaryView.class)
private Singer representSinger;
@JsonView(ViewModel.SummaryView.class)
private List<Track> tracks;
}
|
@Data
@Builder
public class Singer {
@JsonView(ViewModel.DetailView.class)
private String name;
@JsonView(ViewModel.SummaryView.class)
private String nickname;
@JsonView(ViewModel.DetailView.class)
private String managementCompany;
}
|
@Data
@Builder
public class Track {
private String trackId;
@JsonView(ViewModel.DefaultView.class)
private String trackTitle;
@JsonView(ViewModel.DefaultView.class)
private String trackNo;
@JsonView(ViewModel.SummaryView.class)
private String genre;
@JsonView(ViewModel.DetailView.class)
private Singer singer;
}
|
TC에서 아래와 같이 변경 후 수행해 보자.
parser.printPrettyJson(album, ViewModel.SummaryView.class); |
{
"albumId" : "albumId",
"albumName" : "albumName",
"representSinger" : {
"nickname" : "singerNickname"
},
"tracks" : [ {
"trackId" : "trackId1",
"trackTitle" : "No.1 Track",
"trackNo" : "1",
"genre" : "genre"
} ]
}
|
SummaryView 를 사용했기 때문에 DetailView 로 선언된 속성은 제외되었음을 확인할 수 있다.
그래도 여전히 albumId 와 trackId 는 노출되고 있는데, 별도의 @JsonView 옵션을 주지 않은 경우 기본적으로 Json 에 포함되는 것을 확인할 수 있다. 그 이유는 ObjectMapper 설정에 아래 옵션 때문이다.
MapperFeature.DEFAULT_VIEW_INCLUSION
|
위 옵션은 기본값이 True 로 @JsonView 설정이 안 된 속성도 Json 변환 시 기본적으로 포함한다는 의미이다.
이 값을 False로 설정한 뒤 다시 수행해 보자.
MAPPER.configure(MapperFeature.DEFAULT_VIEW_INCLUSION, false); |
{
"albumName" : "albumName",
"representSinger" : {
"nickname" : "singerNickname"
},
"tracks" : [ {
"trackTitle" : "No.1 Track",
"trackNo" : "1",
"genre" : "genre"
} ]
}
|
이제 처음 의도했던 대로 ID 정보가 제외된 것을 확인할 수 있다.
Jackson 의 이러한 기능을 Spring 에서 MessageConverter 설정 시 적용할 수 있다.
@Bean
public MappingJackson2HttpMessageConverter mappingJacksonHttpMessageConverter() {
MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
converter.setPrettyPrint(true);
converter.setObjectMapper(new ObjectMapper());
return converter;
}
|
* 기본값으로 ObjectMapper 를 생성하고 있으나 MapperFeature 옵션을 추가해 주면된다.
- http://tomining.tistory.com/120
- https://github.com/tomining/JavaStudy/tree/master/src/main/java/tomining/java/json/jackson/jsonview
- https://stackoverflow.com/questions/33511013/spring-mvc-test-set-jackson-default-view-inclusion
- http://www.concretepage.com/spring-4/spring-mvc-4-rest-jackson-jsonview-annotation-integration-example#client
'Programing > Java' 카테고리의 다른 글
Java에서 문자열에 포함된 HTML 태그들 제거하기 (0) | 2018.02.08 |
---|---|
Collectors.toMap() 시 IllegalStateException 오류 (0) | 2017.12.26 |
How to use exceptions effectively? (어떻게 Exception을 효율적으로 사용할까?) (0) | 2017.08.28 |
Java에서 String과 new String()의 차이는? (2) | 2017.08.24 |
Jackson을 이용한 org.joda.time.DateTime 파싱하기 (0) | 2017.07.27 |