@@ -4,26 +4,40 @@ package com.openlayer.api.core
4
4
5
5
import com.fasterxml.jackson.annotation.JsonInclude
6
6
import com.fasterxml.jackson.core.JsonGenerator
7
+ import com.fasterxml.jackson.core.JsonParseException
8
+ import com.fasterxml.jackson.core.JsonParser
9
+ import com.fasterxml.jackson.databind.DeserializationContext
7
10
import com.fasterxml.jackson.databind.DeserializationFeature
8
11
import com.fasterxml.jackson.databind.MapperFeature
9
12
import com.fasterxml.jackson.databind.SerializationFeature
10
13
import com.fasterxml.jackson.databind.SerializerProvider
11
14
import com.fasterxml.jackson.databind.cfg.CoercionAction
12
15
import com.fasterxml.jackson.databind.cfg.CoercionInputShape
16
+ import com.fasterxml.jackson.databind.deser.std.StdDeserializer
13
17
import com.fasterxml.jackson.databind.json.JsonMapper
14
18
import com.fasterxml.jackson.databind.module.SimpleModule
15
19
import com.fasterxml.jackson.databind.type.LogicalType
16
20
import com.fasterxml.jackson.datatype.jdk8.Jdk8Module
17
21
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule
18
22
import com.fasterxml.jackson.module.kotlin.kotlinModule
19
23
import java.io.InputStream
24
+ import java.time.DateTimeException
25
+ import java.time.LocalDate
26
+ import java.time.LocalDateTime
27
+ import java.time.ZonedDateTime
28
+ import java.time.format.DateTimeFormatter
29
+ import java.time.temporal.ChronoField
20
30
21
31
fun jsonMapper (): JsonMapper =
22
32
JsonMapper .builder()
23
33
.addModule(kotlinModule())
24
34
.addModule(Jdk8Module ())
25
35
.addModule(JavaTimeModule ())
26
- .addModule(SimpleModule ().addSerializer(InputStreamJsonSerializer ))
36
+ .addModule(
37
+ SimpleModule ()
38
+ .addSerializer(InputStreamSerializer )
39
+ .addDeserializer(LocalDateTime ::class .java, LenientLocalDateTimeDeserializer ())
40
+ )
27
41
.withCoercionConfig(LogicalType .Boolean ) {
28
42
it.setCoercion(CoercionInputShape .Integer , CoercionAction .Fail )
29
43
.setCoercion(CoercionInputShape .Float , CoercionAction .Fail )
@@ -91,7 +105,10 @@ fun jsonMapper(): JsonMapper =
91
105
.disable(MapperFeature .AUTO_DETECT_SETTERS )
92
106
.build()
93
107
94
- private object InputStreamJsonSerializer : BaseSerializer<InputStream>(InputStream : :class) {
108
+ /* * A serializer that serializes [InputStream] to bytes. */
109
+ private object InputStreamSerializer : BaseSerializer<InputStream>(InputStream : :class) {
110
+
111
+ private fun readResolve (): Any = InputStreamSerializer
95
112
96
113
override fun serialize (
97
114
value : InputStream ? ,
@@ -105,3 +122,46 @@ private object InputStreamJsonSerializer : BaseSerializer<InputStream>(InputStre
105
122
}
106
123
}
107
124
}
125
+
126
+ /* *
127
+ * A deserializer that can deserialize [LocalDateTime] from datetimes, dates, and zoned datetimes.
128
+ */
129
+ private class LenientLocalDateTimeDeserializer :
130
+ StdDeserializer <LocalDateTime >(LocalDateTime ::class .java) {
131
+
132
+ companion object {
133
+
134
+ private val DATE_TIME_FORMATTERS =
135
+ listOf (
136
+ DateTimeFormatter .ISO_LOCAL_DATE_TIME ,
137
+ DateTimeFormatter .ISO_LOCAL_DATE ,
138
+ DateTimeFormatter .ISO_ZONED_DATE_TIME ,
139
+ )
140
+ }
141
+
142
+ override fun logicalType (): LogicalType = LogicalType .DateTime
143
+
144
+ override fun deserialize (p : JsonParser , context : DeserializationContext ? ): LocalDateTime {
145
+ val exceptions = mutableListOf<Exception >()
146
+
147
+ for (formatter in DATE_TIME_FORMATTERS ) {
148
+ try {
149
+ val temporal = formatter.parse(p.text)
150
+
151
+ return when {
152
+ ! temporal.isSupported(ChronoField .HOUR_OF_DAY ) ->
153
+ LocalDate .from(temporal).atStartOfDay()
154
+ ! temporal.isSupported(ChronoField .OFFSET_SECONDS ) ->
155
+ LocalDateTime .from(temporal)
156
+ else -> ZonedDateTime .from(temporal).toLocalDateTime()
157
+ }
158
+ } catch (e: DateTimeException ) {
159
+ exceptions.add(e)
160
+ }
161
+ }
162
+
163
+ throw JsonParseException (p, " Cannot parse `LocalDateTime` from value: ${p.text} " ).apply {
164
+ exceptions.forEach { addSuppressed(it) }
165
+ }
166
+ }
167
+ }
0 commit comments