본문 바로가기
Jackson

Jackson Deserialization Annotation

by 이석준석이 2020. 10. 18.

틀린 내용이 있다면 댓글이나 robin00q@naver.com으로 보내주시면 반영하겠습니다,, ^^

 

www.baeldung.com/jackson-annotations

 

Jackson Annotation Examples | Baeldung

The core of Jackson is basically a set of annotations - make sure you understand these well.

www.baeldung.com

을 참고하고, 정리했습니다,,^^


github.com/robin00q/jackson_practice

 

robin00q/jackson_practice

Contribute to robin00q/jackson_practice development by creating an account on GitHub.

github.com

 

모든 코드는 위의 링크에 저장되어있습니다. (IntelliJ의 Springinitializer / spring-boot-starter-web / lombok / java 11 을 사용했습니다)

  • ObjectMapper은 자동으로 의존성 주입되므로 따로 설정할 필요가 없습니다.
  • 테스트 할 때 @SpringBootTest를 선언하거나 new ObjectMapper()를 사용하여 ObjectMapper를 사용하면 됩니다.

Jackson Deserialization(Json 데이터를 Java 객체로 변환) Annotation 

1. @JsonCreator

  • Json 데이터를 Java 객체로 받고 싶은 경우 사용합니다.
  • Constructor(생성자) 위에 Annotation을 추가하여 사용합니다.
  • 파라미터에 @JsonProperty를 사용하여 json key값을 명시합니다.
    • json key값과 Java 객체의 프로퍼티가 같다면 생략 가능합니다.

예시 - 아래의 데이터를 @JsonCreator을 사용하여 Java 객체에 담아보자

{
  "id": 1,
  "name": "My bean"
}

정답 / 테스트

@Getter
@ToString
public class JsonCreatorDTO {
    private Integer id;

    private String name;

    @JsonCreator
    public JsonCreatorDTO(@JsonProperty("id") Integer id, @JsonProperty("name") String name) {
        this.id = id;
        this.name = name;
    }
}
@Test
void test() throws JsonProcessingException {
    // given
    String json = "{\"id\":1,\"name\":\"My bean\"}";

    // when
    JsonCreatorDTO jsonCreatorDTO = new ObjectMapper()
            .readerFor(JsonCreatorDTO.class)
            .readValue(json);

    // then
    assertEquals(jsonCreatorDTO.getId(), 1);
    assertEquals(jsonCreatorDTO.getName(), "My bean");
    System.out.println(jsonCreatorDTO);
}

2. @JacksonInject

  • Json 데이터에서 데이터를 가져오지 않고 injection을 받아 Java 데이터를 채웁니다.

예시 - 아래의 Json Data에 Id 프로퍼티를 Injection받아 Java 객체의 데이터를 채워보자

{
  "name": "My bean"
}
JacksonInjectDTO(id=1, name=My bean)

정답 / 테스트

@Getter
@ToString
public class JacksonInjectDTO {

    @JacksonInject
    private Integer id;

    private String name;

}
@Test
void test() throws JsonProcessingException {
    // given
    String json = "{\"name\":\"My bean\"}";

    // when
    InjectableValues inject = new InjectableValues.Std()
            .addValue(Integer.class, 1);
    JacksonInjectDTO jacksonInjectDTO = new ObjectMapper().reader(inject)
            .forType(JacksonInjectDTO.class)
            .readValue(json);

    // then
    assertEquals(jacksonInjectDTO.getId(), 1);
    assertEquals(jacksonInjectDTO.getName(), "My bean");
    System.out.println(jacksonInjectDTO);
}

3. @JsonAnySetter

  • Map객체를 사용할 경우 유용하게 사용할 수 있습니다.
  • Map객체에 데이터를 추가하는 메소드 위에 @JsonAnySetter를 추가합니다.

예시 - 아래의 데이터를 @JsonAnySetter를 사용하여 attr1, attr2를 추가해보자

{
  "name": "My bean",
  "attr2": "val2",
  "attr1": "val1"
}

정답 / 테스트

@Getter
@ToString
public class JsonAnySetterDTO {
    private String name;

    private Map<String, String> properties = new HashMap<>();

    @JsonAnySetter
    public void addProperties(String key, String value) {
        properties.put(key, value);
    }
}
@Test
void test() throws JsonProcessingException {
    // given
    String json = "{\"name\":\"My bean\",\"attr2\":\"val2\",\"attr1\":\"val1\"}";

    // when
    JsonAnySetterDTO jsonAnySetterDTO = new ObjectMapper().readerFor(JsonAnySetterDTO.class)
            .readValue(json);

    // then
    assertEquals(jsonAnySetterDTO.getProperties().get("attr1"), "val1");
    assertEquals(jsonAnySetterDTO.getProperties().get("attr2"), "val2");
    System.out.println(jsonAnySetterDTO);
}

4. @JsonSetter

  • @JsonProperty대신 Setter 메소드 위에 사용합니다.
    • 프로퍼티와 Json Key값이 다른 경우 @JsonProperty("Json Key 값") 으로 사용합니다.

예시 - 아래의 데이터를 @JsonSetter를 사용하여 받아보자

{
  "id": 1,
  "name": "My bean"
}

정답 / 테스트

@Getter
@ToString
public class JsonSetterDTO {
    private Integer id;
    private String name;

    @JsonSetter("id")
    public void setId(Integer id) {
        this.id = id;
    }

    @JsonSetter("name")
    public void setName(String name) {
        this.name = name;
    }
}
@Test
    void test() throws JsonProcessingException {
        // given
        String json = "{\"id\":1,\"name\":\"My bean\"}";
    
        // when
        JsonSetterDTO jsonSetterDTO = new ObjectMapper().readerFor(JsonSetterDTO.class)
                .readValue(json);
    
        // then
        assertEquals(jsonSetterDTO.getId(), 1);
        assertEquals(jsonSetterDTO.getName(), "My bean");
        System.out.println(jsonSetterDTO);
    }

5. @JsonDeserialize

  • custom한 deserierizer을 선언하여 역직렬화를 할 수 있습니다.
  • 메소드 위에 @JsonDeserialize(using = "내가 정의한 deserializer") 로 사용합니다.

예시 - 아래의 Json을 @JsonDeserialize를 이용하여 Java Object로 가져와라 [LocalDateTime 사용]

{
  "name": "party",
  "eventDate": "2020-10-18 11:11:11"
}

정답 + deserializer / 테스트

@Getter
@ToString
public class JsonDeserializeDTO {

    private String name;

    @JsonDeserialize(using = CustomJsonDeserializer.class)
    private LocalDateTime eventDate;
}
public class CustomJsonDeserializer extends StdDeserializer<LocalDateTime> {

    public static DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

    public CustomJsonDeserializer() {
        this(null);
    }

    protected CustomJsonDeserializer(Class<?> vc) {
        super(vc);
    }

    @Override
    public LocalDateTime deserialize(JsonParser jsonParser, DeserializationContext ctxt) throws IOException, JsonProcessingException {
        String date = jsonParser.getText();
        return LocalDateTime.parse(date, formatter);
    }
}
@Test
void test() throws JsonProcessingException {
    // given
    String json
            = "{\"name\":\"party\",\"eventDate\":\"2020-10-18 11:11:11\"}";

    // when
    JsonDeserializeDTO jsonDeserializeDTO = new ObjectMapper().readerFor(JsonDeserializeDTO.class)
            .readValue(json);

    // then
    assertEquals(jsonDeserializeDTO.getName(), "party");
    assertEquals(jsonDeserializeDTO.getEventDate(), LocalDateTime.parse("2020-10-18 11:11:11", CustomJsonDeserializer.formatter));
    System.out.println(jsonDeserializeDTO);
}

6. @JsonAlias

  • 여러개의 Json Key를 하나의 Java 변수가 받을 수 있도록 설정할 수 있습니다.
  • @JsonAlias({"key1, "key2", ..}) 으로 변수위에 선언할 수 있습니다.

예시 - fName / f_name 을 모두 받을 수 있는 Java 객체를 @JsonAlias를 이용해 만드시오

{
  "fName": "John",
  "lastName": "Green"
}
----
{
  "f_name": "John",
  "lastName": "Green"
}

정답 / 테스트

@Getter
@ToString
public class JsonAliasDTO {
    @JsonAlias({"f_name", "fName"})
    private String firstName;
    private String lastName;
}
@Test
void test() throws JsonProcessingException {
    // given
    String json = "{\"f_name\": \"John\", \"lastName\": \"Green\"}";
    // String json = "{\"fName\": \"John\", \"lastName\": \"Green\"}";

    System.out.println(json);

    // when
    JsonAliasDTO jsonAliasDTO = new ObjectMapper().readerFor(JsonAliasDTO.class)
            .readValue(json);

    // then
    assertEquals(jsonAliasDTO.getFirstName(), "John");
    assertEquals(jsonAliasDTO.getLastName(), "Green");
    System.out.println(jsonAliasDTO);
}

 

'Jackson' 카테고리의 다른 글

Jackson Serialization Annotation  (1) 2020.10.17