OffsetDateTime Deserializer
์คํ๋ง ๋ถํธ์์ ์ฌ์ฉํ๋ ObjectMapper๋ฅผ ์ํด์ Jackson ๋ผ์ด๋ธ๋ฌ๋ฆฌ์์ ์ง์ํ๊ณ ์๋ JavaTimeModule์ ๋ฑ๋กํ์ฌ OffsetDateTime์ ๋ํ Serializer๋ฅผ ๋ฑ๋กํ ์ ์์ต๋๋ค. ๊ธฐ๋ณธ์ผ๋ก ์ ๊ณต๋๋ OffsetDateTimeSerializer๋2025-01-24T00:00:00+09:00 ์ ๊ฐ์ ํจํด์ ๋ํ ๋ณํ์ ์ง์ํ๊ธฐ๋ ํ๊ณ ์ง๋ ์๋ฐ ๋ ์ง ๋ฐ ์๊ฐ ํฌ๋งท์์ ์ฌ๋ฌ ํํ์ ํจํด์ ์ง์ํ๊ธฐ ์ํด DateTimeFormatter๋ฅผ ๋ง๋ค์ด ์ฌ์ฉํ๊ธฐ๋ ํ์์ต๋๋ค.
KDB+์ Timestamp ๋ฌธ์์ด
`timestamp$.z.d
2025.01.24D00:00:00.000000000
`datetime$`timestamp$.z.d
2025.01.24T00:00:00.000
Caused by: com.fasterxml.jackson.databind.exc.InvalidFormatException: Cannot deserialize value of type `java.time.OffsetDateTime` from String "2025-01-24T00:00:00.000000000": Failed to deserialize java.time.OffsetDateTime: (java.time.format.DateTimeParseException) Text '2025-01-24T00:00:00.000000000' could not be parsed at index 29
KDB+๋ผ๊ณ ํ๋ ์๊ณ์ด ๋ฐ์ดํฐ๋ฒ ์ด์ค์ Timestamp๋ JSON์ผ๋ก ๋ณํํ๋ ๊ฒฝ์ฐ2025-01-24T00:00:00.000000000 ํํ์ ๋๋ ธ์ด ์ ๋ฐ๋๋ฅผ ๊ฐ์ง๋ UTC ๊ธฐ์ค์ ๋ฌธ์์ด์ด ๋ฉ๋๋ค. ๋ฐ๋ผ์, ๊ธฐ์กด์ ๋ง๋ค์๋ DateTimeFormatter๋ก๋ ์ปค๋ฒํ ์ ์๋ ํจํด์ด๋ฏ๋ก OffsetDateTime์ผ๋ก ๋ณํํ ์ ์์์ ์ ์ค๋ฅ ๋ก๊ทธ๋ฅผ ํตํด ํ์ธํ ์ ์์ต๋๋ค. ์ด๋ฐ ๊ฒฝ์ฐ์๋ ์ผ๋ฐ์ ์ธISO_OFFSET_DATE_PATTERN์ด ์๋๋ฏ๋ก ObjectMapper์ OffsetDateTime์ ์ํ Deserializer ๋ฅผ ๋ฑ๋กํ์ฌ ์๋ํ๋ DateTimeFormatter๋ฅผ ์ฌ์ฉํ๋๋ก ์ฝ๋๋ฅผ ์์ ํด์ผํ ์ ๋ฐ์ ์์ต๋๋ค.
๋๋ ธ์ด ์ ๋ฐ๋๋ฅผ ์ง์ํ๋ OffsetDateTimeDeserializer
@Bean
public Jackson2ObjectMapperBuilder objectMapperBuilder() {
return new Jackson2ObjectMapperBuilder()
.modules(new JavaTimeModule())
.deserializerByType(OffsetDateTime.class, new OffsetDateTimeDeserializer());
}
private static class OffsetDateTimeDeserializer extends JsonDeserializer<OffsetDateTime> {
@Override
public OffsetDateTime deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException {
String str = jsonParser.getValueAsString();
if (str == null || str.isEmpty()) {
return null;
}
// NOTE: ์ซ์๋ก๋ง ๊ตฌ์ฑ๋๋ ๋ฐ๋ฆฌ์ด ๋จ์์ ํ์์คํฌํ
if (str.matches("^\\d+$")) {
long value = jsonParser.getNumberValue().longValue();
Instant instant = Instant.ofEpochMilli(value);
return OffsetDateTime.ofInstant(instant, ZoneOffset.UTC);
}
try {
return OffsetDateTime.parse(str, DateTimeFormatter.ISO_OFFSET_DATE_TIME);
} catch (DateTimeException e) {
// NOTE: KDB+ Timestamp
return OffsetDateTime.parse(str, DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSSSSSSS").withZone(ZoneOffset.UTC));
}
}
}
์์ฑ๋ ObjectMapper์ Deserializer๋ฅผ ๋ฑ๋กํ ์๋ ์์ง๋ง Jackson2ObjectMapperBuilder ๋ฅผ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ ์๊ณผ ๊ฐ์ด OffsetDateTime ํด๋์ค์ ๋ํ Deserializer๋ฅผ ๋ฑ๋กํ ์ ์๋ ํจ์๋ฅผ ๋ณ๋๋ก ์ ๊ณตํ๊ณ ์์ต๋๋ค. ์ ์์ ์ฝ๋๋ ์ซ์๋ก ๊ตฌ์ฑ๋ ๊ฒฝ์ฐ์ ์ผ๋ฐ์ ์ธ ํฌ๋งท์ผ๋ก ๋ณํ์ ํ ์ ์์ผ๋ฉด๋๋ ธ์ด ์ ๋ฐ๋๋ฅผ ๊ฐ์ง๋ KDB+ ํ์์คํฌํ ๋ฌธ์์ด์ ์ฒ๋ฆฌํ๋๋ก ์์ฑํ ๊ฒ ์ ๋๋ค. ํ๋ก๋์ ์ ์ฝ๋์์๋ ObjectMapper ๋ฟ๋ง ์๋๋ผGson์ ๋ํ Deserializer๋ฅผ ์์ฑํ์ฌ ํจ๊ป ์ฌ์ฉํ๊ณ ์์ต๋๋ค.