From af812603553c53187a6502020162f5abacb7460a Mon Sep 17 00:00:00 2001 From: pricelees Date: Fri, 15 Aug 2025 18:23:59 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20=ED=94=84=EB=A1=A0=ED=8A=B8=EC=97=94?= =?UTF-8?q?=EB=93=9C=EC=99=80=EC=9D=98=20PK=20=ED=98=B8=ED=99=98=EC=9D=84?= =?UTF-8?q?=20=EC=9C=84=ED=95=9C=20Long=20<->=20String=20ObjectMapper=20?= =?UTF-8?q?=EB=AA=A8=EB=93=88=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../roomescape/common/config/JacksonConfig.kt | 39 ++++++++++++++++++- .../common/config/JacksonConfigTest.kt | 14 +++++++ 2 files changed, 52 insertions(+), 1 deletion(-) diff --git a/src/main/kotlin/roomescape/common/config/JacksonConfig.kt b/src/main/kotlin/roomescape/common/config/JacksonConfig.kt index 40232da4..c53a98d8 100644 --- a/src/main/kotlin/roomescape/common/config/JacksonConfig.kt +++ b/src/main/kotlin/roomescape/common/config/JacksonConfig.kt @@ -1,6 +1,9 @@ package roomescape.common.config -import com.fasterxml.jackson.databind.ObjectMapper +import com.fasterxml.jackson.core.JsonGenerator +import com.fasterxml.jackson.core.JsonParser +import com.fasterxml.jackson.databind.* +import com.fasterxml.jackson.databind.module.SimpleModule import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer @@ -9,6 +12,8 @@ import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer import com.fasterxml.jackson.module.kotlin.kotlinModule import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration +import roomescape.common.exception.CommonErrorCode +import roomescape.common.exception.RoomescapeException import java.time.LocalDate import java.time.LocalTime import java.time.format.DateTimeFormatter @@ -20,6 +25,7 @@ class JacksonConfig { fun objectMapper(): ObjectMapper = ObjectMapper() .registerModule(javaTimeModule()) .registerModule(kotlinModule()) + .registerModule(longIdModule()) private fun javaTimeModule(): JavaTimeModule = JavaTimeModule() .addSerializer( @@ -38,4 +44,35 @@ class JacksonConfig { LocalTime::class.java, LocalTimeDeserializer(DateTimeFormatter.ofPattern("HH:mm")) ) as JavaTimeModule + + private fun longIdModule(): SimpleModule { + val simpleModule = SimpleModule() + simpleModule.addSerializer(Long::class.java, LongToStringSerializer()) + simpleModule.addDeserializer(Long::class.java, StringToLongDeserializer()) + return simpleModule + } +} + +class LongToStringSerializer : JsonSerializer() { + override fun serialize(value: Long?, gen: JsonGenerator, serializers: SerializerProvider) { + if (value == null) { + gen.writeNull() + } else { + gen.writeString(value.toString()) + } + } +} + +class StringToLongDeserializer : JsonDeserializer() { + override fun deserialize(p: JsonParser, ctxt: DeserializationContext): Long? { + val text = p.text + if (text.isNullOrBlank()) { + return null + } + return try { + text.toLong() + } catch (_: NumberFormatException) { + throw RoomescapeException(CommonErrorCode.INVALID_INPUT_VALUE) + } + } } diff --git a/src/test/kotlin/roomescape/common/config/JacksonConfigTest.kt b/src/test/kotlin/roomescape/common/config/JacksonConfigTest.kt index c290d1d9..98ca4e91 100644 --- a/src/test/kotlin/roomescape/common/config/JacksonConfigTest.kt +++ b/src/test/kotlin/roomescape/common/config/JacksonConfigTest.kt @@ -52,4 +52,18 @@ class JacksonConfigTest( }.message shouldContain "Text '$hour:$minute:$sec' could not be parsed" } } + + context("Long 타입은 문자열로 (역)직렬화된다.") { + val number = 1234567890L + val serialized: String = objectMapper.writeValueAsString(number) + val deserialized: Long = objectMapper.readValue(serialized, Long::class.java) + + test("Long 직렬화") { + serialized shouldBe "$number" + } + + test("Long 역직렬화") { + deserialized shouldBe number + } + } })