Spring

모든 jackson 어노테이션 종류 파악

기록만이살길 2020. 6. 11. 21:28
반응형

모든 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

@JsonAnySetterMap 을 표준 속성으로 사용할 수있는 유연성을 제공합니다. 직렬화 해제시 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_namefirstName 과 같은 값을 사용하여 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

반응형