generated from pricelees/issue-pr-template
[#5]: 공통 기능 코틀린 마이그레이션 및 패키지 분리 #6
@ -1,40 +1,41 @@
|
|||||||
package roomescape.common.config;
|
package roomescape.common.config
|
||||||
|
|
||||||
import java.time.LocalDate;
|
import com.fasterxml.jackson.databind.ObjectMapper
|
||||||
import java.time.LocalTime;
|
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule
|
||||||
import java.time.format.DateTimeFormatter;
|
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer
|
||||||
|
import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer
|
||||||
import org.springframework.context.annotation.Bean;
|
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer
|
||||||
import org.springframework.context.annotation.Configuration;
|
import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer
|
||||||
|
import com.fasterxml.jackson.module.kotlin.kotlinModule
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import org.springframework.context.annotation.Bean
|
||||||
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
|
import org.springframework.context.annotation.Configuration
|
||||||
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
|
import java.time.LocalDate
|
||||||
import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer;
|
import java.time.LocalTime
|
||||||
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
|
import java.time.format.DateTimeFormatter
|
||||||
import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer;
|
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
public class JacksonConfig {
|
class JacksonConfig {
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public ObjectMapper objectMapper() {
|
fun objectMapper(): ObjectMapper = ObjectMapper()
|
||||||
ObjectMapper objectMapper = new ObjectMapper();
|
.registerModule(javaTimeModule())
|
||||||
objectMapper.registerModule(javaTimeModule());
|
.registerModule(kotlinModule())
|
||||||
return objectMapper;
|
|
||||||
}
|
private fun javaTimeModule(): JavaTimeModule = JavaTimeModule()
|
||||||
|
.addSerializer(
|
||||||
@Bean
|
LocalDate::class.java,
|
||||||
public JavaTimeModule javaTimeModule() {
|
LocalDateSerializer(DateTimeFormatter.ISO_LOCAL_DATE)
|
||||||
JavaTimeModule javaTimeModule = new JavaTimeModule();
|
)
|
||||||
|
.addDeserializer(
|
||||||
javaTimeModule.addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ISO_LOCAL_DATE));
|
LocalDate::class.java,
|
||||||
javaTimeModule.addDeserializer(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ISO_LOCAL_DATE));
|
LocalDateDeserializer(DateTimeFormatter.ISO_LOCAL_DATE)
|
||||||
|
)
|
||||||
javaTimeModule.addSerializer(LocalTime.class, new LocalTimeSerializer(DateTimeFormatter.ofPattern("HH:mm")));
|
.addSerializer(
|
||||||
javaTimeModule.addDeserializer(LocalTime.class,
|
LocalTime::class.java,
|
||||||
new LocalTimeDeserializer(DateTimeFormatter.ofPattern("HH:mm")));
|
LocalTimeSerializer(DateTimeFormatter.ofPattern("HH:mm"))
|
||||||
|
)
|
||||||
return javaTimeModule;
|
.addDeserializer(
|
||||||
}
|
LocalTime::class.java,
|
||||||
|
LocalTimeDeserializer(DateTimeFormatter.ofPattern("HH:mm"))
|
||||||
|
) as JavaTimeModule
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,80 +0,0 @@
|
|||||||
package roomescape.common;
|
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.*;
|
|
||||||
|
|
||||||
import java.time.LocalDate;
|
|
||||||
import java.time.LocalTime;
|
|
||||||
|
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
|
||||||
import org.junit.jupiter.api.DisplayName;
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
||||||
|
|
||||||
import roomescape.common.config.JacksonConfig;
|
|
||||||
|
|
||||||
class JacksonConfigTest {
|
|
||||||
|
|
||||||
private ObjectMapper objectMapper;
|
|
||||||
|
|
||||||
@BeforeEach
|
|
||||||
void setUp() {
|
|
||||||
JacksonConfig jacksonConfig = new JacksonConfig();
|
|
||||||
objectMapper = jacksonConfig.objectMapper();
|
|
||||||
}
|
|
||||||
|
|
||||||
@DisplayName("날짜는 yyyy-MM-dd 형식으로 직렬화 된다.")
|
|
||||||
@Test
|
|
||||||
void dateSerialize() throws JsonProcessingException {
|
|
||||||
// given
|
|
||||||
LocalDate date = LocalDate.parse("2021-07-01");
|
|
||||||
|
|
||||||
// when
|
|
||||||
String json = objectMapper.writeValueAsString(date);
|
|
||||||
LocalDate actual = objectMapper.readValue(json, LocalDate.class);
|
|
||||||
|
|
||||||
// then
|
|
||||||
assertThat(actual.toString()).isEqualTo("2021-07-01");
|
|
||||||
}
|
|
||||||
|
|
||||||
@DisplayName("시간은 HH:mm 형식으로 직렬화된다.")
|
|
||||||
@Test
|
|
||||||
void timeSerialize() throws JsonProcessingException {
|
|
||||||
// given
|
|
||||||
LocalTime time = LocalTime.parse("12:30:00");
|
|
||||||
|
|
||||||
// when
|
|
||||||
String json = objectMapper.writeValueAsString(time);
|
|
||||||
LocalTime actual = objectMapper.readValue(json, LocalTime.class);
|
|
||||||
|
|
||||||
// then
|
|
||||||
assertThat(actual.toString()).isEqualTo("12:30");
|
|
||||||
}
|
|
||||||
|
|
||||||
@DisplayName("yyyy-MM-dd 형식의 문자열은 LocalDate로 역직렬화된다.")
|
|
||||||
@Test
|
|
||||||
void dateDeserialize() throws JsonProcessingException {
|
|
||||||
// given
|
|
||||||
String json = "\"2021-07-01\"";
|
|
||||||
|
|
||||||
// when
|
|
||||||
LocalDate actual = objectMapper.readValue(json, LocalDate.class);
|
|
||||||
|
|
||||||
// then
|
|
||||||
assertThat(actual).isEqualTo(LocalDate.of(2021, 7, 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
@DisplayName("HH:mm 형식의 문자열은 LocalTime으로 역직렬화된다.")
|
|
||||||
@Test
|
|
||||||
void timeDeserialize() throws JsonProcessingException {
|
|
||||||
// given
|
|
||||||
String json = "\"12:30\"";
|
|
||||||
|
|
||||||
// when
|
|
||||||
LocalTime actual = objectMapper.readValue(json, LocalTime.class);
|
|
||||||
|
|
||||||
// then
|
|
||||||
assertThat(actual).isEqualTo(LocalTime.of(12, 30));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
55
src/test/java/roomescape/common/config/JacksonConfigTest.kt
Normal file
55
src/test/java/roomescape/common/config/JacksonConfigTest.kt
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
package roomescape.common.config
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper
|
||||||
|
import com.fasterxml.jackson.databind.exc.InvalidFormatException
|
||||||
|
import io.kotest.assertions.throwables.shouldThrow
|
||||||
|
import io.kotest.core.spec.style.FunSpec
|
||||||
|
import io.kotest.matchers.shouldBe
|
||||||
|
import io.kotest.matchers.string.shouldContain
|
||||||
|
import java.time.LocalDate
|
||||||
|
import java.time.LocalTime
|
||||||
|
|
||||||
|
class JacksonConfigTest(
|
||||||
|
private val objectMapper: ObjectMapper = JacksonConfig().objectMapper()
|
||||||
|
) : FunSpec({
|
||||||
|
|
||||||
|
context("날짜는 yyyy-mm-dd 형식이다.") {
|
||||||
|
val date = "2025-07-14"
|
||||||
|
val serialized: String = objectMapper.writeValueAsString(LocalDate.parse(date))
|
||||||
|
val deserialized: LocalDate = objectMapper.readValue(serialized, LocalDate::class.java)
|
||||||
|
|
||||||
|
test("LocalDate 직렬화") {
|
||||||
|
serialized shouldBe "\"$date\""
|
||||||
|
}
|
||||||
|
|
||||||
|
test("LocalDate 역직렬화") {
|
||||||
|
deserialized shouldBe LocalDate.parse(date)
|
||||||
|
}
|
||||||
|
|
||||||
|
test("형식이 잘못되면 InvalidFormatException을 던진다.") {
|
||||||
|
shouldThrow<InvalidFormatException> {
|
||||||
|
objectMapper.readValue("\"2025/07/14\"", LocalDate::class.java)
|
||||||
|
}.message shouldContain "Text '2025/07/14' could not be parsed"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
context("시간은 HH:mm 형식이다.") {
|
||||||
|
val (hour, minute, sec) = Triple(12, 30, 45)
|
||||||
|
val serialized: String = objectMapper.writeValueAsString(LocalTime.of(hour, minute, sec))
|
||||||
|
val deserialized: LocalTime = objectMapper.readValue(serialized, LocalTime::class.java)
|
||||||
|
|
||||||
|
test("LocalTime 직렬화") {
|
||||||
|
serialized shouldBe "\"$hour:$minute\""
|
||||||
|
}
|
||||||
|
|
||||||
|
test("LocalTime 역직렬화") {
|
||||||
|
deserialized shouldBe LocalTime.of(hour, minute)
|
||||||
|
}
|
||||||
|
|
||||||
|
test("형식이 잘못되면 InvalidFormatException을 던진다.") {
|
||||||
|
shouldThrow<InvalidFormatException> {
|
||||||
|
objectMapper.readValue("\"$hour:$minute:$sec\"", LocalTime::class.java)
|
||||||
|
}.message shouldContain "Text '$hour:$minute:$sec' could not be parsed"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
Loading…
x
Reference in New Issue
Block a user