Spring Boot, JSON 변환, LocalDateTime을 ISO8601으로 출력하기

개요

Spring Boot(또는 Spring 4 MVC)는 HTTP 요청-응답시 application/json;charset=UTF-8 형식의 메시지에 대해 JSON 문자열-Java 오브젝트를 자동으로 상호 변환해준다. 이 기능을 입맛에 맞게 잘 사용하려면 동작의 상세 원리를 이해하는 것이 필수이다.

먼저 읽어볼만한 글

POJO-JSON 상호 변환의 상세

  • MappingJackson2HttpMessageConverter 클래스가 Spring Boot 초기 구동시 JacksonHttpMessageConvertersConfiguration 클래스에 의해 싱글턴 빈으로 등록되어 POJO-JSON간의 상호 변환을 수행한다.

  • MappingJackson2HttpMessageConverter는 이름에서 보여지듯이 Java 진영에서 널리 쓰이는 JSON 라이브러리인 Jackson(Spring Boot 1.3.5 기준 Jackson 2.6 내장)을 사용하여 메시지를 상호 변환한다.

  • MappingJackson2HttpMessageConverterHttpMessageConverter 인터페이스의 구현체로 read(), write() 메써드를 이용하여 JSON을 처리한다. 내부적으로는 Jackson이 제공하는 ObjectMapper 클래스를 사용하는데 커스텀 설정을 적용하여 미리 빈으로 등록해두면 변환시 자동으로 해당 빈을 대신 사용한다.

ObjectMapper 커스터마이징

현재 시간을 JSON을 반환하는 간단한 기능의 컨트롤러 클래스를 아래와 같이 작성해보자.

package com.jsonobject.example;

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import java.time.LocalDateTime;

@Controller
@RequestMapping(value = "/now")
public class JsonController {

    @RequestMapping(method = RequestMethod.GET)
    public ResponseEntity<?> now() {

        return new ResponseEntity<LocalDateTime>(LocalDateTime.now(), HttpStatus.OK);
    }
}

위 기능을 요청하면 아래와 같이 응답한다.

{
    "hour": 2,
    "minute": 7,
    "nano": 468000000,
    "second": 1,
    "dayOfMonth": 11,
    "dayOfWeek": "SATURDAY",
    "dayOfYear": 163,
    "month": "JUNE",
    "monthValue": 6,
    "year": 2016,
    "chronology": {
        "id": "ISO",
        "calendarType": "iso8601"
    }
}

위는 Java 8이 제공하는 LocalDateTime 오브젝트가 JSON으로 변환되어 출력된 결과이다. 클라이언트에게 보여주기에는 지나치게 친절하면서 장황한 데이터 출력이다. 최근 REST API의 추세는 날짜/시간을 ISO-8601 형식으로 응답하는 것이다. ObjectMapper 오브젝트의 커스터마이징 빈 등록으로 이를 해결할 수 있다.


/build.gradle의 의존성에 아래 라이브러리를 추가한다.

dependencies {
    compile group: 'com.fasterxml.jackson.datatype', name: 'jackson-datatype-jsr310', version: '2.7.4'
}
  • Jackson Datatype JSR310LocalDateTime을 비롯한 Java 8의 날짜/시간 관련 오브젝트를 인식할 수 있는 Jackson 라이브러리의 추가 모듈이다.

커스터마이징된 빈을 등록하기 위한 @Configuration 클래스를 아래와 같이 작성한다.

package com.jsonobject.example;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;

@Configuration
public class JsonConfig {

    @Bean
    public ObjectMapper objectMapper() {

        return Jackson2ObjectMapperBuilder.json().featuresToDisable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS).modules(new JavaTimeModule()).build();
    }
}

동일한 요청을 다시 해보자. 전과 다르게 아래와 같이 ISO-8601 형식으로 출력되는 것을 확인할 수 있다.

"2016-06-11T03:57:47.146"

참고 글

저작자 표시 비영리 동일 조건 변경 허락
신고