본문 바로가기
JAVA

Jackson Library (ObjectMapper)

by 공부 안하고 싶은 사람 2021. 2. 9.
반응형

의존성

spring-starter-web -> spring-starter-json -> Jackson 라이브러리

spring boot라면 start-web만 의존받으면되고, 그렇지 않을경우 jackson을 별도로 추가하면 된다.

 

 

ObjectMapper
JSON문자열 <- Object
objectMapper.writeValueAsString(Object object)

 

JSON문자열 -> Object
objectMapper.readValue(json, Car.class)
(json은 json형식의 string)

 

JSON문자열-> JsonNode
JsonNode jsonNode = objectMapper.readTree(json);
String color = jsonNode.get("color").asText();
String type = jsonNode.get("type").asText();

 

Json문자열 -> Map
Map<String, Object > map = objectMapper.readValue(jsonStr, new TypeReference<Map<String, Object>>() {});

 

 

TypeReference

generic type erasure라는 특성(자바1.5부터 나온 generic은 하위 호환성을 위해 런타임에는 generic 정보가 없어진다.)

따라서 List와 같은 자료형으로 변환하기 위해선 추상클래스를 구현하는 익명클래스를 만들어 변환해야 generic type이 런타임에도 유지된다.

New TypeReference<List<Object>>(){};

 

 

Annotation

  • JsonProperty : Json 변환시 key 이름을 변경할 수 있도록 @JsonProperty(“chang_name”)
  • JsonIgnore : 변환시 무시할 필드 설정
  • JsonIgnoreProperties : 클래스에서 어떤 변수명들을 변환시 무시할지 설정
  • JsonIgnoreType : 적용된 클래스는 모든 참조(연관)된 클래스의 변환에서 무시됨 (적용된 클래스를 갖는 다른 클래스를 변환시 적용된 클래스는 변환되지 않는다.)
  • JsonInclude : notnull과 같은 규칙인 데이터들을 제외하고 변환할 수 있는 규칙들 등록 (클래스/필드에 적용)
    • (JsonInclude.Include에 있는 enum 값)을 추가할 수 있다.
    • 혹은 해당 내용을 application.yml에 설정하여 전체적용. spring.jackson.default-propert-inclusion: non_null
    • 각각 mapper에서 변환시 설정을 등록할 수 있다. mapper.setSerializationInclusion(Inclusion.NON_NULL);
  • JsonFormat : Value에 해당되는 값의 형식을 지정할 수 있다. (시간 표시에 많이 사용되는 듯하다.)
    • @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime date;

 

 

Config

디비 <-> 자바8 날짜 형식 맞춰줄 수 있도록 설정

  1. 모든 필드마다 @JsonFormat 어노테이션 달아주기 귀찮으니 LocalDate, LocalTime, LocalDateTime 등등에 대한 기본 Custom Serializer / Deserializer를 만들어주자.
  2. 특정 필드는 잭슨의 기본 Deserializer를 써야할 수도 있으니 jackson-datatype-jsr310을 Dependency에 추가해두자.
  3. @DateTimeFormat은 제대로 안 먹히는 필드도 있으니 @JsonFormat을 애용하도록 하자.
@Configuration
public class JacksonConfig {

    private static final String LOCAL_DATE_FORMAT = "yyyy-MM-dd";
    private static final String LOCAL_TIME_FORMAT = "HH:mm:ss";
    private static final String LOCAL_DATE_TIME_FORMAT = "yyyy-MM-dd'T'HH:mm:ss";

    @Bean
    public ObjectMapper objectMapper() {
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.registerModule(java8DateTimeModule());
        objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        return objectMapper;
    }

    @Bean
    public Module java8DateTimeModule() {
        SimpleModule module = new SimpleModule();
        module.addSerializer(LocalDate.class, (localDate, jsonGenerator,  serializerProvide) -> {
        jsonGenerator.writeString(DateTimeFormatter.ofPattern(LOCAL_DATE_FORMAT).format(localDate));
            });
        module.addDeserializer(LocalDate.class, (jsonParser, deserializationContext) -> {
                return LocalDate.parse(jsonParser.getValueAsString(), DateTimeFormatter.ofPattern(LOCAL_DATE_FORMAT));
        });

        module.addSerializer(LocalTime.class, new JsonSerializer<LocalTime>() {
            @Override
            public void serialize(
                LocalTime localTime, JsonGenerator jsonGenerator, SerializerProvider serializerProvider)
                throws IOException {
                jsonGenerator.writeString(DateTimeFormatter.ofPattern(LOCAL_TIME_FORMAT).format(localTime));
            }
        });
        module.addDeserializer(LocalTime.class, new JsonDeserializer<LocalTime>() {
            @Override
            public LocalTime deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException {
                return LocalTime.parse(jsonParser.getValueAsString(), DateTimeFormatter.ofPattern(LOCAL_TIME_FORMAT));
            }
        });
      
        module.addSerializer(LocalDateTime.class, new JsonSerializer<LocalDateTime>() {
            @Override
            public void serialize(
                LocalDateTime localDateTime, JsonGenerator jsonGenerator, SerializerProvider serializerProvider)
                throws IOException {
                jsonGenerator.writeString(DateTimeFormatter.ofPattern(LOCAL_DATE_TIME_FORMAT).format(localDateTime));
            }
        });
        module.addDeserializer(LocalDateTime.class, new JsonDeserializer<LocalDateTime>() {
            @Override
            public LocalDateTime deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException {
                return LocalDateTime.parse(jsonParser.getValueAsString(), DateTimeFormatter.ofPattern(LOCAL_DATE_TIME_FORMAT));
            }
        });
        return module;
    }
}

 

 

 

참고 : https://velog.io/@hanblueblue/%EB%B2%88%EC%97%AD-Intro-to-the-Jackson-ObjectMapper-%EC%98%88%EC%A0%9C-%EC%BD%94%EB%93%9C

 

https://perfectacle.github.io/2018/01/15/jackson-local-date-time-deserialize/

 

[번역] Intro to the Jackson ObjectMapper + 예제 코드

ObjectMapper와 커스텀 serializer/deserializer

velog.io

 

728x90
반응형

'JAVA' 카테고리의 다른 글

SOLID  (0) 2021.06.28
디자인 패턴  (0) 2021.06.28
인코딩 변환  (0) 2021.04.29
스트림  (0) 2021.02.19
함수형 인터페이스  (0) 2021.02.19

댓글