코딩딩/Error

LocalDateTime ResponseBody

전낙타 2024. 9. 11. 13:28

DTO에 담겨있는 LocalDateTime을 직렬화 하지 않고 그냥 ResponseBody에 넣어버리니 다음과 같이 list 형식으로 넘어가버리더라.

왜 배열?

이를 해결하기 위해 CustomLocalDateTimeSerializer를 제작하고 Server에서 문자열에서 포메팅해 Discord bot으로 넘겨주는 로직을 작성했다.

 

DTO

package study.surviveoutsidethejunglespring.algorithm.dto;

import static study.surviveoutsidethejunglespring.config.JacksonConfig.*;

import java.time.LocalDateTime;

import com.fasterxml.jackson.databind.annotation.JsonSerialize;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.ToString;
import study.surviveoutsidethejunglespring.algorithm.entity.Algorithm;
import study.surviveoutsidethejunglespring.guild.entity.Guild;

@Getter
@ToString
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class AlgorithmTypeDto {
	private Long guildInfoId;
	private Long algorithmForumId;

	@JsonSerialize(using = CustomLocalDateTimeSerializer.class)
	private LocalDateTime registrationAt;
	private String algorithmType;

	public static AlgorithmTypeDto of(Algorithm algorithm, Guild guild) {
		return AlgorithmTypeDto.builder()
			.guildInfoId(guild.getGuildInfoId())
			.algorithmForumId(guild.getAlgorithmForumId())
			.registrationAt(algorithm.getRegistrationAt())
			.algorithmType(algorithm.getAlgorithmType())
			.build();
	}

}

 

JacksonConfig

package study.surviveoutsidethejunglespring.config;

import java.io.IOException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;

@Configuration
public class JacksonConfig {

	@Bean
	public ObjectMapper objectMapper() {
		SimpleModule module = new SimpleModule();
		module.addSerializer(LocalDateTime.class, new CustomLocalDateTimeSerializer());

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

	public static class CustomLocalDateTimeSerializer extends JsonSerializer<LocalDateTime> {
		private static final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy년 MM월 dd일 EEEE", Locale.KOREAN);

		@Override
		public void serialize(LocalDateTime value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
			if (value != null) {
				gen.writeString(formatter.format(value));
			}
		}
	}
}

 

왜 이런 문제가 발생하나 알아봤더니

LocalDateTime을 ResponseBody로 전달할 때, Jackson과 같은 JSON 직렬화 라이브러리가 LocalDateTime을 직렬화할 때 기본적으로 리스트(배열) 형식으로 변환하기 때문이란다. LocalDateTime은 복잡한 시간 정보를 포함하고 있어서, Jackson은 이를 [year, month, day, hour, minute, second, nanosecond]와 같은 배열로 전달한다.

 

결론!

결포메팅은 서버에서!