모든 jackson 어노테이션 종류 파악
1. 개요
이 글에서는 Jackson Annotations에 대해 자세히 살펴 보겠습니다 .
기존 어노테이션을 사용하는 방법, 사용자 정의 어노테이션을 만드는 방법 및 마지막으로 비활성화하는 방법을 살펴 보겠습니다
2. Jackson 직렬화 어노테이션
먼저 직렬화 어노테이션을 살펴 보겠습니다. 직렬화는 자바를 json현태로 변경하는것을 의미합니다.
2.1. @JsonAnyGetter
@JsonAnyGetter의 어노테이션은 사용의 유연성 수 있도록 지도 표준 속성으로 필드를.
다음은 간단한 예입니다. ExtendableBean 엔티티에는 name 특성과 키 / 값 쌍의 형태로 확장 가능한 속성 세트가 있습니다.
{
"name":"My bean",
"attr2":"val2",
"attr1":"val1"
}
이 엔티티의 인스턴스를 직렬화하면 맵의 모든 키-값이 표준 일반 속성으로 가져옵니다 .
{
"name":"My bean",
"attr2":"val2",
"attr1":"val1"
}
그리고이 엔티티의 직렬화가 실제로 어떻게 보이는지 :
@Test
public void whenSerializingUsingJsonAnyGetter_thenCorrect()
throws JsonProcessingException {
ExtendableBean bean = new ExtendableBean("My bean");
bean.add("attr1", "val1");
bean.add("attr2", "val2");
String result = new ObjectMapper().writeValueAsString(bean);
assertThat(result, containsString("attr1"));
assertThat(result, containsString("val1"));
}
@JsonAnyGetter () 를 비활성화하기 위해 enabled 옵션 인수 를 false 로 사용할 수도 있습니다 . 이 경우 지도 는 JSON으로 변환되며 직렬화 후 속성 변수 아래에 나타납니다 .
2.2. JsonGetter
@JsonGetter의 어노테이션은의 대안 @JsonProperty의 게터 법 등을 표시하는 어노테이션.
다음 예제에서 – 우리는 getTheName () 메소드 를 MyBean 엔티티 의 name 속성의 getter 메소드로 지정 합니다 .
public class MyBean {
public int id;
private String name;
@JsonGetter("name")
public String getTheName() {
return name;
}
}
그리고 이것이 실제로 작동하는 방법은 다음과 같습니다.
@Test
public void whenSerializingUsingJsonGetter_thenCorrect()
throws JsonProcessingException {
MyBean bean = new MyBean(1, "My bean");
String result = new ObjectMapper().writeValueAsString(bean);
assertThat(result, containsString("My bean"));
assertThat(result, containsString("1"));
}
2.3. @JsonPropertyOrder
@JsonPropertyOrder 어노테이션을 사용 하여 직렬화에서 특성 순서 를 지정할 수 있습니다 .
MyBean 엔티티 의 프로퍼티에 대한 커스텀 순서를 설정하자 :
@JsonPropertyOrder({ "name", "id" })
public class MyBean {
public int id;
public String name;
}
다음은 직렬화의 출력입니다.
{
"name":"My bean",
"id":1
}
그리고 간단한 테스트 :
@Test
public void whenSerializingUsingJsonPropertyOrder_thenCorrect()
throws JsonProcessingException {
MyBean bean = new MyBean(1, "My bean");
String result = new ObjectMapper().writeValueAsString(bean);
assertThat(result, containsString("My bean"));
assertThat(result, containsString("1"));
}
@JsonPropertyOrder (alphabetic = true) 를 사용하여 속성을 알파벳순으로 정렬 할 수도 있습니다 . 이 경우 직렬화 출력은 다음과 같습니다.
{
"id":1,
"name":"My bean"
}
2.4. @JsonRawValue
@JsonRawValue의 어노테이션을 수행 할 수 있습니다 정확하게는 그대로 속성을 직렬화 잭슨을 지시합니다 .
다음 예제에서는 @JsonRawValue 를 사용 하여 일부 사용자 정의 JSON을 엔티티 값으로 임베드합니다.
public class RawBean {
public String name;
@JsonRawValue
public String json;
}
엔티티를 직렬화 한 결과는 다음과 같습니다.
{
"name":"My bean",
"json":{
"attr":false
}
}
그리고 간단한 테스트 :
@Test
public void whenSerializingUsingJsonRawValue_thenCorrect()
throws JsonProcessingException {
RawBean bean = new RawBean("My bean", "{\"attr\":false}");
String result = new ObjectMapper().writeValueAsString(bean);
assertThat(result, containsString("My bean"));
assertThat(result, containsString("{\"attr\":false}"));
}
이 어노테이션의 활성화 여부를 정의 하는 선택적 부울 인수 값 을 사용할 수도 있습니다 .
2.5. JsonValue
@JsonValue 는 라이브러리가 전체 인스턴스를 직렬화하는 데 사용할 단일 메소드를 나타냅니다.
예를 들어, 열거, 우리는 어노테이션 getName 와 @JsonValue을 그래서 그러한 단체가 그 이름을 통해 연재된다 :
public enum TypeEnumWithValue {
TYPE1(1, "Type A"), TYPE2(2, "Type 2");
private Integer id;
private String name;
// standard constructors
@JsonValue
public String getName() {
return name;
}
}
우리의 테스트 :
@Test
public void whenSerializingUsingJsonValue_thenCorrect()
throws JsonParseException, IOException {
String enumAsString = new ObjectMapper()
.writeValueAsString(TypeEnumWithValue.TYPE1);
assertThat(enumAsString, is(""Type A""));
}
2.6. @JsonRootName
@JsonRootName의 어노테이션이 사용됩니다 - 포장이 사용 가능한 경우 - 사용되는 루트 래퍼의 이름을 지정할 수 있습니다.
랩핑은 사용자 를 다음과 같이 직렬화하는 대신 다음을 의미합니다 .
{
"id": 1,
"name": "John"
}
다음과 같이 포장됩니다.
{
"User": {
"id": 1,
"name": "John"
}
}
예제를 보자 . @JsonRootName 어노테이션을 사용 하여이 잠재적 래퍼 엔티티의 이름을 표시 할 것이다 .
@JsonRootName(value = "user")
public class UserWithRoot {
public int id;
public String name;
}
기본적으로 랩퍼 이름은 UserWithRoot 클래스 이름입니다 .어노테이션을 사용하면 더 깔끔한 사용자를 얻을 수 있습니다.
@Test
public void whenSerializingUsingJsonRootName_thenCorrect()
throws JsonProcessingException {
UserWithRoot user = new User(1, "John");
ObjectMapper mapper = new ObjectMapper();
mapper.enable(SerializationFeature.WRAP_ROOT_VALUE);
String result = mapper.writeValueAsString(user);
assertThat(result, containsString("John"));
assertThat(result, containsString("user"));
}
다음은 직렬화의 출력입니다.
{
"user":{
"id":1,
"name":"John"
}
}
Jackson 2.4부터는 XML과 같은 데이터 형식과 함께 사용할 수 있는 새로운 선택적 인수 네임 스페이스 를 사용할 수 있습니다. 추가하면 정규화 된 이름의 일부가됩니다.
@JsonRootName(value = "user", namespace="users")
public class UserWithRootNamespace {
public int id;
public String name;
// ...
}
XmlMapper로 직렬화 하면 출력은 다음과 같습니다.
<user xmlns="users">
<id xmlns="">1</id>
<name xmlns="">John</name>
<items xmlns=""/>
</user>
2.7. @JsonSerialize
@JsonSerialize 는 엔터티를 마샬링 할 때 사용할 사용자 지정 serializer를 나타냅니다 .
간단한 예를 봅시다. 우리가 사용하는거야 @JsonSerialize을 직렬화 EVENTDATE의 A의 특성 CustomDateSerializer를 :
public class EventWithSerializer {
public String name;
@JsonSerialize(using = CustomDateSerializer.class)
public Date eventDate;
}
간단한 사용자 지정 Jackson 직렬 변환기는 다음과 같습니다.
public class CustomDateSerializer extends StdSerializer<Date> {
private static SimpleDateFormat formatter
= new SimpleDateFormat("dd-MM-yyyy hh:mm:ss");
public CustomDateSerializer() {
this(null);
}
public CustomDateSerializer(Class<Date> t) {
super(t);
}
@Override
public void serialize(
Date value, JsonGenerator gen, SerializerProvider arg2)
throws IOException, JsonProcessingException {
gen.writeString(formatter.format(value));
}
}
테스트에서 이것을 사용하자 :
@Test
public void whenSerializingUsingJsonSerialize_thenCorrect()
throws JsonProcessingException, ParseException {
SimpleDateFormat df
= new SimpleDateFormat("dd-MM-yyyy hh:mm:ss");
String toParse = "20-12-2014 02:30:00";
Date date = df.parse(toParse);
EventWithSerializer event = new EventWithSerializer("party", date);
String result = new ObjectMapper().writeValueAsString(event);
assertThat(result, containsString(toParse));
}
3. Jackson Deserialization 어노테이션
다음으로 Jackson deserialization 어노테이션을 살펴 보겠습니다.
3.1. JsonCreator
@JsonCreator 어노테이션을 사용하여 역 직렬화에 사용되는 생성자 / 공장을 조정할 수 있습니다 .
필요한 대상 엔터티와 정확히 일치하지 않는 일부 JSON을 역 직렬화해야 할 때 매우 유용합니다.
예를 보자. 다음 JSON을 역 직렬화해야한다고 가정 해보십시오.
{
"id":1,
"theName":"My bean"
}
그러나,이없는 theName의 목표 기업에 대한 필드 - 만이 이름 필드. 이제 엔티티 자체를 변경하고 싶지 않습니다. @JsonCreator로 생성자에 어노테이션을 달고 @JsonProperty 어노테이션을 사용하여 비 정렬 화 프로세스를 조금 더 제어하면 됩니다.
public class BeanWithCreator {
public int id;
public String name;
@JsonCreator
public BeanWithCreator(
@JsonProperty("id") int id,
@JsonProperty("theName") String name) {
this.id = id;
this.name = name;
}
}
이것을 실제로 보자.
@Test
public void whenDeserializingUsingJsonCreator_thenCorrect()
throws IOException {
String json = "{\"id\":1,\"theName\":\"My bean\"}";
BeanWithCreator bean = new ObjectMapper()
.readerFor(BeanWithCreator.class)
.readValue(json);
assertEquals("My bean", bean.name);
}
3.2. @JacksonInject
@JacksonInject 는 속성이 JSON 데이터가 아니라 주입에서 값을 가져옴을 나타냅니다.
다음 예에서 – @JacksonInject 를 사용하여 속성 ID 를 주입합니다 .
public class BeanWithInject {
@JacksonInject
public int id;
public String name;
}
그리고 이것이 작동하는 방법은 다음과 같습니다.
@Test
public void whenDeserializingUsingJsonInject_thenCorrect()
throws IOException {
String json = "{\"name\":\"My bean\"}";
InjectableValues inject = new InjectableValues.Std()
.addValue(int.class, 1);
BeanWithInject bean = new ObjectMapper().reader(inject)
.forType(BeanWithInject.class)
.readValue(json);
assertEquals("My bean", bean.name);
assertEquals(1, bean.id);
}
3.3. JsonAnySetter
@JsonAnySetter 는 Map 을 표준 속성으로 사용할 수있는 유연성을 제공합니다. 직렬화 해제시 JSON의 특성이 단순히 맵에 추가됩니다.
이것이 어떻게 작동하는지 봅시다 – @JsonAnySetter 를 사용 하여 엔터티 ExtendableBean 을 직렬화 해제합니다 :
public class ExtendableBean {
public String name;
private Map<String, String> properties;
@JsonAnySetter
public void add(String key, String value) {
properties.put(key, value);
}
}
이것은 직렬화 해제해야하는 JSON입니다.
{
"name":"My bean",
"attr2":"val2",
"attr1":"val1"
}
그리고 이것이 어떻게이 모든 것이 함께 묶여 있는지를 보여줍니다 :
@Test
public void whenDeserializingUsingJsonAnySetter_thenCorrect()
throws IOException {
String json
= "{\"name\":\"My bean\",\"attr2\":\"val2\",\"attr1\":\"val1\"}";
ExtendableBean bean = new ObjectMapper()
.readerFor(ExtendableBean.class)
.readValue(json);
assertEquals("My bean", bean.name);
assertEquals("val2", bean.getProperties().get("attr2"));
}
3.4. JsonSetter
@JsonSetter는 대안이다 @JsonProperty - 세터 방법과 그 표시 방법.
JSON 데이터를 읽어야하지만 대상 엔터티 클래스가 해당 데이터 와 정확히 일치하지 않으므로 프로세스를 조정하여 적합하도록해야합니다.
다음 예제에서는 MyBean 엔티티 에서 s etTheName () 메소드를 name 특성 의 setter로 지정합니다 .
public class MyBean {
public int id;
private String name;
@JsonSetter("name")
public void setTheName(String name) {
this.name = name;
}
}
이제 JSON 데이터를 언 마샬링해야 할 때 완벽하게 작동합니다.
@Test
public void whenDeserializingUsingJsonSetter_thenCorrect()
throws IOException {
String json = "{\"id\":1,\"name\":\"My bean\"}";
MyBean bean = new ObjectMapper()
.readerFor(MyBean.class)
.readValue(json);
assertEquals("My bean", bean.getTheName());
}
3.5. JsonDeserialize
@JsonDeserialize 는 사용자 지정 디시리얼라이저 사용을 나타냅니다.
이것이 어떻게 나타나는지 보자. @JsonDeserialize 를 사용 하여 CustomDateDeserializer 와 함께 eventDate 속성 을 직렬화 해제합니다 .
public class EventWithSerializer {
public String name;
@JsonDeserialize(using = CustomDateDeserializer.class)
public Date eventDate;
}
다음은 사용자 지정 디시리얼라이저입니다.
public class CustomDateDeserializer
extends StdDeserializer<Date> {
private static SimpleDateFormat formatter
= new SimpleDateFormat("dd-MM-yyyy hh:mm:ss");
public CustomDateDeserializer() {
this(null);
}
public CustomDateDeserializer(Class<?> vc) {
super(vc);
}
@Override
public Date deserialize(
JsonParser jsonparser, DeserializationContext context)
throws IOException {
String date = jsonparser.getText();
try {
return formatter.parse(date);
} catch (ParseException e) {
throw new RuntimeException(e);
}
}
}
그리고 연속 테스트는 다음과 같습니다.
@Test
public void whenDeserializingUsingJsonDeserialize_thenCorrect()
throws IOException {
String json
= "{"name":"party","eventDate":"20-12-2014 02:30:00"}";
SimpleDateFormat df
= new SimpleDateFormat("dd-MM-yyyy hh:mm:ss");
EventWithSerializer event = new ObjectMapper()
.readerFor(EventWithSerializer.class)
.readValue(json);
assertEquals(
"20-12-2014 02:30:00", df.format(event.eventDate));
}
3.6 @JsonAlias
@JsonAlias는 정의 직렬화하는 동안 속성에 대한 하나 이상의 대체 이름을 .
이 어노테이션이 간단한 예에서 어떻게 작동하는지 봅시다 :
public class AliasBean {
@JsonAlias({ "fName", "f_name" })
private String firstName;
private String lastName;
}
여기에는 POJO가 있으며 fName , f_name 및 firstName 과 같은 값을 사용하여 JSON을 POJO 의 firstName 변수에 직렬화 해제하려고합니다 .
그리고이 어노테이션이 예상대로 작동하는지 확인하는 테스트가 있습니다.
@Test
public void whenDeserializingUsingJsonAlias_thenCorrect() throws IOException {
String json = "{\"fName\": \"John\", \"lastName\": \"Green\"}";
AliasBean aliasBean = new ObjectMapper().readerFor(AliasBean.class).readValue(json);
assertEquals("John", aliasBean.getFirstName());
}
4. Jackson Property Inclusion Annotations
4.1. JsonIgnoreProperties
@JsonIgnoreProperties 는 Jackson이 무시할 속성 또는 속성 목록을 표시하는 클래스 수준 어노테이션입니다.
직렬화 에서 속성 ID 를 무시하는 간단한 예를 살펴 보겠습니다 .
@JsonIgnoreProperties({ "id" })
public class BeanWithIgnore {
public int id;
public String name;
}
다음은 무시가 발생하는지 확인하는 테스트입니다.
@Test
public void whenSerializingUsingJsonIgnoreProperties_thenCorrect()
throws JsonProcessingException {
BeanWithIgnore bean = new BeanWithIgnore(1, "My bean");
String result = new ObjectMapper()
.writeValueAsString(bean);
assertThat(result, containsString("My bean"));
assertThat(result, not(containsString("id")));
}
예외없이 JSON 입력에서 알 수없는 속성을 무시하기 위해 @JsonIgnoreProperties 어노테이션 의 ignoreUnknown = true 를 설정할 수 있습니다 .
4.2. JsonIgnore
@JsonIgnore의 어노테이션 필드 레벨에서 무시 될 수있는 속성을 표시하는 데 사용됩니다.
직렬화 에서 속성 ID 를 무시하기 위해 @JsonIgnore 를 사용 하십시오 .
public class BeanWithIgnore {
@JsonIgnore
public int id;
public String name;
}
그리고 테스트는 id 가 성공적으로 무시 되었는지확인합니다.
@Test
public void whenSerializingUsingJsonIgnore_thenCorrect()
throws JsonProcessingException {
BeanWithIgnore bean = new BeanWithIgnore(1, "My bean");
String result = new ObjectMapper()
.writeValueAsString(bean);
assertThat(result, containsString("My bean"));
assertThat(result, not(containsString("id")));
}
4.3. @JsonIgnoreType
@JsonIgnoreType 은 어노테이션이있는 유형의 모든 특성이 무시 되도록 표시합니다.
어노테이션을 사용하여 Name 유형의 모든 속성을 무시 하도록 표시합시다 .
public class User {
public int id;
public Name name;
@JsonIgnoreType
public static class Name {
public String firstName;
public String lastName;
}
}
무시가 올바르게 작동하는지 확인하는 간단한 테스트는 다음과 같습니다.
@Test
public void whenSerializingUsingJsonIgnoreType_thenCorrect()
throws JsonProcessingException, ParseException {
User.Name name = new User.Name("John", "Doe");
User user = new User(1, name);
String result = new ObjectMapper()
.writeValueAsString(user);
assertThat(result, containsString("1"));
assertThat(result, not(containsString("name")));
assertThat(result, not(containsString("John")));
}
4.4. @JsonInclude
@JsonInclude 를 사용 하여 비어 있거나 null / 기본값 인 속성을 제외 할 수 있습니다 .
직렬화에서 null을 제외하는 예를 살펴 보겠습니다.
@JsonInclude(Include.NON_NULL)
public class MyBean {
public int id;
public String name;
}
전체 테스트는 다음과 같습니다.
public void whenSerializingUsingJsonInclude_thenCorrect()
throws JsonProcessingException {
MyBean bean = new MyBean(1, null);
String result = new ObjectMapper()
.writeValueAsString(bean);
assertThat(result, containsString("1"));
assertThat(result, not(containsString("name")));
}
4.5. @JsonAutoDetect
@JsonAutoDetect 는 속성이 표시되고 표시되지 않는 기본 의미를 무시할 수 있습니다 .
간단한 예제를 통해 어노테이션이 어떻게 도움이되는지 살펴 보겠습니다. 개인 속성 직렬화를 활성화 해 보겠습니다.
@JsonAutoDetect(fieldVisibility = Visibility.ANY)
public class PrivateBean {
private int id;
private String name;
}
그리고 테스트 :
@Test
public void whenSerializingUsingJsonAutoDetect_thenCorrect()
throws JsonProcessingException {
PrivateBean bean = new PrivateBean(1, "My bean");
String result = new ObjectMapper()
.writeValueAsString(bean);
assertThat(result, containsString("1"));
assertThat(result, containsString("My bean"));
}
5. Jackson 다형성 유형 처리 어노테이션
다음으로 Jackson 다형성 유형 처리 어노테이션을 살펴 보겠습니다.
@JsonTypeInfo
– 직렬화에 포함 할 유형 정보의 세부 사항을 나타냅니다.
@JsonSubTypes
– 어노테이션이 달린 유형의 하위 유형을 나타냅니다.
@JsonTypeName
– 어노테이션이있는 클래스에 사용할 논리 유형 이름을 정의합니다.
더 복잡한 예제를보고 @JsonTypeInfo , @JsonSubTypes 및 @JsonTypeName 세 가지를 모두 사용 하여 엔티티 Zoo 를 직렬화 / 직렬화하십시오 .
public class Zoo {
public Animal animal;
@JsonTypeInfo(
use = JsonTypeInfo.Id.NAME,
include = As.PROPERTY,
property = "type")
@JsonSubTypes({
@JsonSubTypes.Type(value = Dog.class, name = "dog"),
@JsonSubTypes.Type(value = Cat.class, name = "cat")
})
public static class Animal {
public String name;
}
@JsonTypeName("dog")
public static class Dog extends Animal {
public double barkVolume;
}
@JsonTypeName("cat")
public static class Cat extends Animal {
boolean likesCream;
public int lives;
}
}
직렬화를 수행 할 때 :
@Test
public void whenSerializingPolymorphic_thenCorrect()
throws JsonProcessingException {
Zoo.Dog dog = new Zoo.Dog("lacy");
Zoo zoo = new Zoo(dog);
String result = new ObjectMapper()
.writeValueAsString(zoo);
assertThat(result, containsString("type"));
assertThat(result, containsString("dog"));
}
Zoo 인스턴스를 Dog로 직렬화하면 다음 과 같은 결과가 발생합니다.
{
"animal": {
"type": "dog",
"name": "lacy",
"barkVolume": 0
}
}
이제 직렬화 해제를 위해 다음 JSON 입력으로 시작하겠습니다.
{
"animal":{
"name":"lacy",
"type":"cat"
}
}
그리고 이것이 어떻게 Zoo 인스턴스에 비 정렬 화되는지 봅시다 :
@Test
public void whenDeserializingPolymorphic_thenCorrect()
throws IOException {
String json = "{\"animal\":{\"name\":\"lacy\",\"type\":\"cat\"}}";
Zoo zoo = new ObjectMapper()
.readerFor(Zoo.class)
.readValue(json);
assertEquals("lacy", zoo.animal.name);
assertEquals(Zoo.Cat.class, zoo.animal.getClass());
}
6. Jackson 기본적인 어노테이션
다음은 Jackson의 일반적인 어노테이션에 대해 설명하겠습니다.
6.1. JsonProperty
@JsonProperty 어노테이션을 추가 하여 JSON으로 특성 이름을 표시 할 수 있습니다 .
비표준 게터 및 세터를 처리 할 때 @JsonProperty 를 사용 하여 속성 이름 을 직렬화 / 직렬화합니다 .
public class MyBean {
public int id;
private String name;
@JsonProperty("name")
public void setTheName(String name) {
this.name = name;
}
@JsonProperty("name")
public String getTheName() {
return name;
}
}
우리의 테스트 :
@Test
public void whenUsingJsonProperty_thenCorrect()
throws IOException {
MyBean bean = new MyBean(1, "My bean");
String result = new ObjectMapper().writeValueAsString(bean);
assertThat(result, containsString("My bean"));
assertThat(result, containsString("1"));
MyBean resultBean = new ObjectMapper()
.readerFor(MyBean.class)
.readValue(result);
assertEquals("My bean", resultBean.getTheName());
}
6.2. JsonFormat
@JsonFormat의 날짜 / 시간 값을 직렬화 할 때 어노테이션은 형식을 지정합니다.
다음 예제에서 – @JsonFormat 을 사용 하여 eventDate 속성의 형식을 제어합니다 .
public class EventWithFormat {
public String name;
@JsonFormat(
shape = JsonFormat.Shape.STRING,
pattern = "dd-MM-yyyy hh:mm:ss")
public Date eventDate;
}
그리고 여기 테스트가 있습니다 :
@Test
public void whenSerializingUsingJsonFormat_thenCorrect()
throws JsonProcessingException, ParseException {
SimpleDateFormat df = new SimpleDateFormat("dd-MM-yyyy hh:mm:ss");
df.setTimeZone(TimeZone.getTimeZone("UTC"));
String toParse = "20-12-2014 02:30:00";
Date date = df.parse(toParse);
EventWithFormat event = new EventWithFormat("party", date);
String result = new ObjectMapper().writeValueAsString(event);
assertThat(result, containsString(toParse));
}
6.3. JsonUnwrapped
@JsonUnwrapped 는 직렬화 / 역 직렬화 될 때 랩핑 해제 / 플랫 닝해야하는 값을 정의합니다.
그것이 어떻게 작동하는지 정확히 보자. 우리는 속성 이름 을 풀기 위해 어노테이션을 사용할 것입니다 :
public class UnwrappedUser {
public int id;
@JsonUnwrapped
public Name name;
public static class Name {
public String firstName;
public String lastName;
}
}
이제이 클래스의 인스턴스를 직렬화 해 봅시다 :
@Test
public void whenSerializingUsingJsonUnwrapped_thenCorrect()
throws JsonProcessingException, ParseException {
UnwrappedUser.Name name = new UnwrappedUser.Name("John", "Doe");
UnwrappedUser user = new UnwrappedUser(1, name);
String result = new ObjectMapper().writeValueAsString(user);
assertThat(result, containsString("John"));
assertThat(result, not(containsString("name")));
}
출력의 모양은 다음과 같습니다. 정적 중첩 클래스의 필드는 다른 필드와 함께 래핑되지 않습니다.
{
"id":1,
"firstName":"John",
"lastName":"Doe"
}
6.4. JsonView
@JsonView 는 직렬화 / 역 직렬화에 속성이 포함될 뷰를 나타냅니다.
예제는 그 작동 방식을 정확하게 보여줍니다. @JsonView 를 사용 하여 Item 엔터티 의 인스턴스를 serialize합니다 .
뷰부터 시작하겠습니다 :
public class Views {
public static class Public {}
public static class Internal extends Public {}
}
이제 뷰를 사용하여 Item 엔터티가 있습니다.
public class Item {
@JsonView(Views.Public.class)
public int id;
@JsonView(Views.Public.class)
public String itemName;
@JsonView(Views.Internal.class)
public String ownerName;
}
마지막으로 – 전체 테스트 :
@Test
public void whenSerializingUsingJsonView_thenCorrect()
throws JsonProcessingException {
Item item = new Item(2, "book", "John");
String result = new ObjectMapper()
.writerWithView(Views.Public.class)
.writeValueAsString(item);
assertThat(result, containsString("book"));
assertThat(result, containsString("2"));
assertThat(result, not(containsString("John")));
}
6.5. @JsonManagedReference, @JsonBackReference
@JsonManagedReference 및 @JsonBackReference 어노테이션 부모 / 자식 관계를 처리 할 수있는 루프 주변 일을.
다음 예제에서 – @JsonManagedReference 및 @JsonBackReference 를 사용 하여 ItemWithRef 엔티티 를 직렬화합니다 .
public class ItemWithRef {
public int id;
public String itemName;
@JsonManagedReference
public UserWithRef owner;
}
우리의 UserWithRef 엔티티 :
public class UserWithRef {
public int id;
public String name;
@JsonBackReference
public List<ItemWithRef> userItems;
}
그리고 테스트 :
@Test
public void whenSerializingUsingJacksonReferenceAnnotation_thenCorrect()
throws JsonProcessingException {
UserWithRef user = new UserWithRef(1, "John");
ItemWithRef item = new ItemWithRef(2, "book", user);
user.addItem(item);
String result = new ObjectMapper().writeValueAsString(item);
assertThat(result, containsString("book"));
assertThat(result, containsString("John"));
assertThat(result, not(containsString("userItems")));
}
6.6. JsonIdentityInfo
@JsonIdentityInfo 는 값을 직렬화 / 역 직렬화 할 때 (예 : 무한 재귀 유형의 문제를 처리 할 때) 개체 ID를 사용해야 함을 나타냅니다.
다음 예에서 - 우리는이 ItemWithIdentity의 와 엔티티 와 양방향 관계 UserWithIdentity의 실체를 :
@JsonIdentityInfo(
generator = ObjectIdGenerators.PropertyGenerator.class,
property = "id")
public class ItemWithIdentity {
public int id;
public String itemName;
public UserWithIdentity owner;
}
그리고 UserWithIdentity 엔티티 :
@JsonIdentityInfo(
generator = ObjectIdGenerators.PropertyGenerator.class,
property = "id")
public class UserWithIdentity {
public int id;
public String name;
public List<ItemWithIdentity> userItems;
}
이제 무한 재귀 문제가 어떻게 처리되는지 봅시다 :
@Test
public void whenSerializingUsingJsonIdentityInfo_thenCorrect()
throws JsonProcessingException {
UserWithIdentity user = new UserWithIdentity(1, "John");
ItemWithIdentity item = new ItemWithIdentity(2, "book", user);
user.addItem(item);
String result = new ObjectMapper().writeValueAsString(item);
assertThat(result, containsString("book"));
assertThat(result, containsString("John"));
assertThat(result, containsString("userItems"));
}
다음은 직렬화 된 항목 및 사용자의 전체 출력입니다.
{
"id": 2,
"itemName": "book",
"owner": {
"id": 1,
"name": "John",
"userItems": [
2
]
}
}
6.7. JsonFilter
@JsonFilter의 어노테이션 직렬화시에 사용하는 필터를 지정합니다.
예를 보자. 먼저 엔터티를 정의하고 필터를 가리 킵니다.
@JsonFilter("myFilter")
public class BeanWithFilter {
public int id;
public String name;
}
이제 전체 테스트에서 이름 을 제외한 다른 모든 속성 을 직렬화에서 제외하는 필터를 정의합니다 .
@Test
public void whenSerializingUsingJsonFilter_thenCorrect()
throws JsonProcessingException {
BeanWithFilter bean = new BeanWithFilter(1, "My bean");
FilterProvider filters
= new SimpleFilterProvider().addFilter(
"myFilter",
SimpleBeanPropertyFilter.filterOutAllExcept("name"));
String result = new ObjectMapper()
.writer(filters)
.writeValueAsString(bean);
assertThat(result, containsString("My bean"));
assertThat(result, not(containsString("id")));
}
7. Custom Jackson 어노테이션
다음으로, 사용자 정의 Jackson 어노테이션을 작성하는 방법을 살펴 보겠습니다. @JacksonAnnotationsInside 어노테이션 을 사용할 수 있습니다 .
@Retention(RetentionPolicy.RUNTIME)
@JacksonAnnotationsInside
@JsonInclude(Include.NON_NULL)
@JsonPropertyOrder({ "name", "id", "dateCreated" })
public @interface CustomAnnotation {}
이제 엔티티에 새로운 어노테이션을 사용하면 :
@CustomAnnotation
public class BeanWithCustomAnnotation {
public int id;
public String name;
public Date dateCreated;
}
기존 어노테이션을 단축형으로 사용할 수있는 더 간단한 사용자 정의 어노테이션으로 결합하는 방법을 볼 수 있습니다.
@Test
public void whenSerializingUsingCustomAnnotation_thenCorrect()
throws JsonProcessingException {
BeanWithCustomAnnotation bean
= new BeanWithCustomAnnotation(1, "My bean", null);
String result = new ObjectMapper().writeValueAsString(bean);
assertThat(result, containsString("My bean"));
assertThat(result, containsString("1"));
assertThat(result, not(containsString("dateCreated")));
}
직렬화 프로세스의 출력 :
{
"name":"My bean",
"id":1
}
8. Jackson MixIn 어노테이션
다음 – Jackson MixIn 어노테이션을 사용하는 방법을 살펴 보겠습니다.
예를 들어 User 유형의 속성을 무시하기 위해 MixIn 어노테이션을 사용합니다 .
public class Item {
public int id;
public String itemName;
public User owner;
}
@JsonIgnoreType
public class MyMixInForIgnoreType {}
이것을 실제로 보자.
@Test
public void whenSerializingUsingMixInAnnotation_thenCorrect()
throws JsonProcessingException {
Item item = new Item(1, "book", null);
String result = new ObjectMapper().writeValueAsString(item);
assertThat(result, containsString("owner"));
ObjectMapper mapper = new ObjectMapper();
mapper.addMixIn(User.class, MyMixInForIgnoreType.class);
result = mapper.writeValueAsString(item);
assertThat(result, not(containsString("owner")));
}
9. Jackson Annotation 비활성화
마지막으로 모든 Jackson 어노테이션 을 비활성화하는 방법을 알아 보겠습니다. MapperFeature 를 비활성화하면 됩니다. 다음 예제와 같이 USE_ANNOTATIONS :
@JsonInclude(Include.NON_NULL)
@JsonPropertyOrder({ "name", "id" })
public class MyBean {
public int id;
public String name;
}
이제 어노테이션을 비활성화 한 후에는 아무런 효과가 없으며 라이브러리의 기본값이 적용됩니다.
@Test
public void whenDisablingAllAnnotations_thenAllDisabled()
throws IOException {
MyBean bean = new MyBean(1, null);
ObjectMapper mapper = new ObjectMapper();
mapper.disable(MapperFeature.USE_ANNOTATIONS);
String result = mapper.writeValueAsString(bean);
assertThat(result, containsString("1"));
assertThat(result, containsString("name"));
}
어노테이션을 비활성화하기 전의 직렬화 결과 :
{"id":1}
어노테이션을 비활성화 한 후 직렬화의 결과 :
{
"id":1,
"name":null
}
10. 결론
이 튜토리얼은 Jackson 어노테이션에 대해 심도있게 다루었으며, 어노테이션을 올바르게 사용할 수있는 유연성의 표면을 긁어 냈습니다.
이 모든 예제와 코드 스 니펫의 구현은 GitHub 프로젝트 에서 찾을 수 있습니다. 이 프로젝트 는 Maven 기반 프로젝트이므로 가져 와서 쉽게 실행할 수 있어야합니다.
참고
https://www.baeldung.com/jackson-annotations#1-jsonignoreproperties
'Spring' 카테고리의 다른 글
RestTemplate에서 List 다루기 (0) | 2020.06.14 |
---|---|
RestTemaplte 사용방법 (0) | 2020.06.13 |
이중화된 시스템 Redis를 통한 Spring security session관리 (0) | 2020.06.13 |
Spring 에서Global Error, Exception handling하는 방법 (0) | 2020.06.12 |
Swagger 를 통한 Spring Rest API 자동화 (0) | 2020.06.10 |