generated from pricelees/issue-pr-template
feat: LocalDateTime / OffsetDateTime을 ISO 8601 형식으로 직렬화하는 ObjectMapper 모듈 추가
This commit is contained in:
parent
2e2b71743f
commit
477415b3ba
@ -14,16 +14,21 @@ import org.springframework.context.annotation.Bean
|
|||||||
import org.springframework.context.annotation.Configuration
|
import org.springframework.context.annotation.Configuration
|
||||||
import roomescape.common.exception.CommonErrorCode
|
import roomescape.common.exception.CommonErrorCode
|
||||||
import roomescape.common.exception.RoomescapeException
|
import roomescape.common.exception.RoomescapeException
|
||||||
import java.time.LocalDate
|
import java.time.*
|
||||||
import java.time.LocalTime
|
|
||||||
import java.time.format.DateTimeFormatter
|
import java.time.format.DateTimeFormatter
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
class JacksonConfig {
|
class JacksonConfig {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private val ISO_OFFSET_DATE_TIME_FORMATTER: DateTimeFormatter =
|
||||||
|
DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ssXXX")
|
||||||
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
fun objectMapper(): ObjectMapper = ObjectMapper()
|
fun objectMapper(): ObjectMapper = ObjectMapper()
|
||||||
.registerModule(javaTimeModule())
|
.registerModule(javaTimeModule())
|
||||||
|
.registerModule(dateTimeModule())
|
||||||
.registerModule(kotlinModule())
|
.registerModule(kotlinModule())
|
||||||
.registerModule(longIdModule())
|
.registerModule(longIdModule())
|
||||||
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
|
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
|
||||||
@ -52,6 +57,12 @@ class JacksonConfig {
|
|||||||
simpleModule.addDeserializer(Long::class.java, StringToLongDeserializer())
|
simpleModule.addDeserializer(Long::class.java, StringToLongDeserializer())
|
||||||
return simpleModule
|
return simpleModule
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun dateTimeModule(): SimpleModule {
|
||||||
|
val simpleModule = SimpleModule()
|
||||||
|
simpleModule.addSerializer(LocalDateTime::class.java, LocalDateTimeSerializer())
|
||||||
|
simpleModule.addSerializer(OffsetDateTime::class.java, OffsetDateTimeSerializer())
|
||||||
|
return simpleModule
|
||||||
}
|
}
|
||||||
|
|
||||||
class LongToStringSerializer : JsonSerializer<Long>() {
|
class LongToStringSerializer : JsonSerializer<Long>() {
|
||||||
@ -77,3 +88,28 @@ class StringToLongDeserializer : JsonDeserializer<Long>() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class LocalDateTimeSerializer : JsonSerializer<LocalDateTime>() {
|
||||||
|
override fun serialize(
|
||||||
|
value: LocalDateTime,
|
||||||
|
gen: JsonGenerator,
|
||||||
|
serializers: SerializerProvider
|
||||||
|
) {
|
||||||
|
value.atZone(ZoneId.systemDefault())
|
||||||
|
.toOffsetDateTime()
|
||||||
|
.also {
|
||||||
|
gen.writeString(it.format(ISO_OFFSET_DATE_TIME_FORMATTER))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class OffsetDateTimeSerializer : JsonSerializer<OffsetDateTime>() {
|
||||||
|
override fun serialize(
|
||||||
|
value: OffsetDateTime,
|
||||||
|
gen: JsonGenerator,
|
||||||
|
serializers: SerializerProvider
|
||||||
|
) {
|
||||||
|
gen.writeString(value.format(ISO_OFFSET_DATE_TIME_FORMATTER))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -7,7 +7,10 @@ import io.kotest.core.spec.style.FunSpec
|
|||||||
import io.kotest.matchers.shouldBe
|
import io.kotest.matchers.shouldBe
|
||||||
import io.kotest.matchers.string.shouldContain
|
import io.kotest.matchers.string.shouldContain
|
||||||
import java.time.LocalDate
|
import java.time.LocalDate
|
||||||
|
import java.time.LocalDateTime
|
||||||
import java.time.LocalTime
|
import java.time.LocalTime
|
||||||
|
import java.time.OffsetDateTime
|
||||||
|
import java.time.ZoneOffset
|
||||||
|
|
||||||
class JacksonConfigTest(
|
class JacksonConfigTest(
|
||||||
private val objectMapper: ObjectMapper = JacksonConfig().objectMapper()
|
private val objectMapper: ObjectMapper = JacksonConfig().objectMapper()
|
||||||
@ -66,4 +69,24 @@ class JacksonConfigTest(
|
|||||||
deserialized shouldBe number
|
deserialized shouldBe number
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
context("OffsetDateTime은 ISO 8601 형식으로 직렬화된다.") {
|
||||||
|
val date = LocalDate.of(2025, 7, 14)
|
||||||
|
val time = LocalTime.of(12, 30, 0)
|
||||||
|
val dateTime = OffsetDateTime.of(date, time, ZoneOffset.ofHours(9))
|
||||||
|
val serialized: String = objectMapper.writeValueAsString(dateTime)
|
||||||
|
|
||||||
|
test("OffsetDateTime 직렬화") {
|
||||||
|
serialized shouldBe "\"2025-07-14T12:30:00+09:00\""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
context("LocalDateTime은 ISO 8601 형식으로 직렬화된다.") {
|
||||||
|
val dateTime = LocalDateTime.of(2025, 7, 14, 12, 30, 0)
|
||||||
|
val serialized: String = objectMapper.writeValueAsString(dateTime)
|
||||||
|
|
||||||
|
test("LocalDateTime 직렬화") {
|
||||||
|
serialized shouldBe "\"2025-07-14T12:30:00+09:00\""
|
||||||
|
}
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user