본문 바로가기
Jackson

Jackson Serialization Annotation

by 이석준석이 2020. 10. 17.

틀린 내용이 있다면 댓글이나 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 Serialization(Java POJO Object To Json) Annotation

1. @JsonAnyGetter

  • Java 객체 내에서 Map을 사용할 경우 사용합니다.
  • getter 메소드 위에 사용합니다.

예제 - 아래와 같은 JSON 데이터를 만들어보자.

{
    "blog":"tistory",
    "name":"sukjunelee"
}

 

정답 / 테스트

public class JsonAnyGetterDTO {
    private Map<String, String> properties = new HashMap<>();

    @JsonAnyGetter
    public Map<String, String> getProperties() {
        return properties;
    }
}

 

writerWithDefaultPrettyPrinter() 함수를 사용하여 포맷팅 된 상태로 출력할 수 있습니다.

@Test
void test() throws JsonProcessingException {
    // given
    JsonAnyGetterDTO jsonAnyGetterDTO = new JsonAnyGetterDTO();
    jsonAnyGetterDTO.getProperties().put("blog", "tistory");
    jsonAnyGetterDTO.getProperties().put("name", "sukjunelee");

    // when
    String json = new ObjectMapper()
            .writerWithDefaultPrettyPrinter()
            .writeValueAsString(jsonAnyGetterDTO);

    // then
    assertEquals(json.contains("tistory"), true);
    assertEquals(json.contains("sukjunelee"), true);
    System.out.println(json);
}

 

@JsonAnyGetter(enabled = false) 를 사용하면 아래와 같이 properties 아래에 JSON이 출력된 모습을 확인할 수 있습니다.

{
  "properties" : {
    "name" : "sukjunelee",
    "blog" : "tistory"
  }
}

2. @JsonGetter

  • @JsonProperty를 대체하여 getter 메소드 위에 사용할 수 있습니다.

예제 - 아래와 같은 JSON 데이터를 만들어보자.

{
  "name" : "sjlee",
  "by" : "jsonGetter"
}

 

정답 / 테스트

public class JsonGetterDTO {
    String name;
    String by;

    @JsonGetter
    public String getName() {
        return name;
    }

    @JsonGetter
    public String getBy() {
        return by;
    }
}
@Test
void test() throws JsonProcessingException {
    // given
    JsonGetterDTO jsonGetterDTO = new JsonGetterDTO();
    jsonGetterDTO.name = "sjlee";
    jsonGetterDTO.by = "jsonGetter";

    // when
    String json = new ObjectMapper()
            .writerWithDefaultPrettyPrinter()
            .writeValueAsString(jsonGetterDTO);

    // then
    assertEquals(json.contains("sjlee"), true);
    assertEquals(json.contains("jsonGetter"), true);
    System.out.println(json);
}

3. @JsonPropertyOrder

  • Json Serialization을 했을 경우에 프로퍼티가 출력되는 순서를 지정할 수 있습니다.
  • JAVA 객체의 순서를 유지하며 JSON이 출력되지 않기 때문에 사용합니다.
  • 정의한 순서대로 위에서부터 아래로 JSON이 형성됩니다.

예제 - 아래와 같은 순서로 Json을 출력하고 싶다면

{
  "grade" : 1,
  "habit" : "soccer",
  "name" : "sjlee"
}
@JsonPropertyOrder({"grade", "habit", "name"})
public class JsonPropertyOrderDTO {
    String name;
    Long grade;
    String habit;
}

4. @JsonRawValue

  • JSON 값 자체를 내가 선언하여 출력하도록 지정할 수 있습니다.
  • 프로퍼티 위에 사용하며 Setter / Builder 등으로 값을 지정합니다.

예제 - 아래와 같이 JSON을 출력하자

{
  "name": "sjlee",
  "age": 27,
  "rawValue": {
    "attr": rawvalue
  }
}

 

정답 / 테스트

@Builder
public class JsonRawValueDTO {
    String name;
    Long age;

    @JsonRawValue
    String rawValue;

    @JsonGetter
    public String getName() {
        return name;
    }

    @JsonGetter
    public Long getAge() {
        return age;
    }
}
@Test
void test() throws JsonProcessingException {
    // given
    JsonRawValueDTO jsonRawValueDTO = JsonRawValueDTO.builder()
            .name("sjlee")
            .age(27L)
            .rawValue("{\"attr\":raw value}")
            .build();

    // when
    String json = new ObjectMapper()
            .writerWithDefaultPrettyPrinter()
            .writeValueAsString(jsonRawValueDTO);

    // then
    assertEquals(json.contains("sjlee"), true);
    assertEquals(json.contains("27"), true);
    assertEquals(json.contains("{\"attr\":raw value}"), true);
    System.out.println(json);
}

 

테스트에서의 출력은 아래와 같이 출력이 됩니다.

{
  "name" : "sjlee",
  "age" : 27,
  "rawValue" : {"attr":raw value}
}

포매팅을 예쁘게 해서 보고 싶다면 아래의 사이트와 같은(JSON Viewer) 를 참조해서 출력해보세요.


5. @JsonValue

  • JSON의 리턴 값을 어떤 규격화 된 포맷으로 리턴하고 싶을 때 사용하면 유용합니다.
  • 클래스 내에서 한번만 사용할 수 있습니다. 
  • 함수 위에 사용하며, 해당 함수의 리턴값으로 JSON이 Serialization 됩니다.

예시

  • id, name, age 프로퍼티가 있는 JAVA 객체에서 리턴하는 JSON 포맷이 아래와 같은 경우
  • id + " 이름은 : " + name + " 나이는 : " + age로 리턴하고 싶다면
"1 이름은 : sjlee 나이는 : 27"

 

정답 / 테스트

@Builder
public class JsonValueDTO {

    private Integer id;
    private String name;

    private Integer age;

    @JsonValue
    public String returnJsonValue() {
        return id + " 이름은 : " + name + " 나이는 : " + age;
    }
}
@Test
void test() throws JsonProcessingException {
    JsonValueDTO jsonValueDTO = JsonValueDTO.builder()
            .id(1)
            .name("sjlee")
            .age(27)
            .build();

    String content = new ObjectMapper().writerWithDefaultPrettyPrinter().writeValueAsString(jsonValueDTO);

    System.out.println(content);
}

6. @JsonRootName

  • JSON 객체를 Wrapping 하고 싶을 때 사용합니다.
  • 클래스 위에 사용하며 @JsonRootName(value = "내가 Wrapping 하고 싶은 값") 으로 사용합니다.

wrapping 이란? 

  • 아래와 같이 Json 객체를 Wrap 하는 것.
{
  "name" : "sjlee",
  "age" : 27
}
{
  "user" : {
    "name" : "sjlee",
    "age" : 27
  }
}

예시 (위의 user로 Wrapping 한 Json을 만들어보자)

 

정답 / 테스트 (@Getter 어노테이션을 사용하면 자동으로 Getter위에 @JsonGetter 가 사용됩니다.)

@Builder
@JsonRootName(value = "user")
@Getter
public class JsonRootNameDTO {
    String name;
    Integer age;
}
@Test
void test() throws JsonProcessingException {
    // given
    JsonRootNameDTO jsonRootNameDTO = JsonRootNameDTO.builder()
            .name("sjlee")
            .age(27)
            .build();

    // when
    String json = new ObjectMapper()
            .enable(SerializationFeature.WRAP_ROOT_VALUE)
            .writerWithDefaultPrettyPrinter()
            .writeValueAsString(jsonRootNameDTO);

    // then
    assertEquals(json.contains("user"), true);
    System.out.println(json);
}

7. @JsonSerialize

  • Custom한 Serializer를 정의하고, 정의한 것 처럼 Serialize를 할 경우 사용
  • @JsonSerilize("serializer클래스".class)

예시 - LocalDateTime을 [yyyy-MM-dd] 포맷 Json을 출력하게 하는 JsonSelierlize를 사용 해보자.

{
  "name" : "sjlee",
  "localDateTime" : "2020-10-17"
}

 

정답 + Serializer (DateTimeFormatter.ofPattern 사용) / 테스트

@Builder
@Getter
public class JsonSerializeDTO {
    private String name;

    @JsonSerialize(using = CustomJsonSerializer.class)
    private LocalDateTime localDateTime;
}
public class CustomJsonSerializer extends StdSerializer<LocalDateTime> {

    public CustomJsonSerializer() {
        this(null);
    }

    public CustomJsonSerializer(Class<LocalDateTime> t) {
        super(t);
    }

    @Override
    public void serialize(LocalDateTime value, JsonGenerator gen, SerializerProvider provider) throws IOException {
        gen.writeString(value.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
    }
}
@Test
void test() throws JsonProcessingException {
    JsonSerializeDTO jsonSerializeDTO = JsonSerializeDTO.builder()
            .name("sjlee")
            .localDateTime(LocalDateTime.now())
            .build();

    String json = new ObjectMapper()
            .writerWithDefaultPrettyPrinter()
            .writeValueAsString(jsonSerializeDTO);

    System.out.println(json);
}

'Jackson' 카테고리의 다른 글

Jackson Deserialization Annotation  (0) 2020.10.18