com.lightningkite.lightningserver.serialization.BsonOverrides.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of server-core Show documentation
Show all versions of server-core Show documentation
A set of tools to fill in/replace what Ktor is lacking in.
The newest version!
package com.lightningkite.lightningserver.serialization
import com.github.jershell.kbson.*
import com.lightningkite.lightningdb.DurationMsSerializer
import kotlinx.serialization.*
import kotlinx.serialization.builtins.serializer
import kotlinx.serialization.descriptors.*
import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder
import kotlinx.serialization.modules.*
import org.bson.BsonType
import java.math.BigDecimal
import java.time.*
import java.util.*
import java.util.concurrent.TimeUnit
import java.util.regex.Pattern
import kotlin.reflect.KProperty
val BsonOverrides = SerializersModule {
contextual(Duration::class, DurationMsSerializer)
contextual(UUID::class, com.github.jershell.kbson.UUIDSerializer)
// contextual(ObjectId::class, ObjectIdSerializer)
contextual(BigDecimal::class, BigDecimalSerializer)
contextual(ByteArray::class, ByteArraySerializer)
contextual(Instant::class, MongoInstantSerializer)
// contextual(ZonedDateTime::class, MongoZonedDateTimeSerializer)
// contextual(OffsetDateTime::class, MongoOffsetDateTimeSerializer)
// contextual(OffsetTime::class, MongoOffsetTimeSerializer)
contextual(LocalDate::class, MongoLocalDateSerializer)
contextual(LocalDateTime::class, MongoLocalDateTimeSerializer)
contextual(LocalTime::class, MongoLocalTimeSerializer)
// contextual(BsonTimestamp::class, BsonTimestampSerializer)
contextual(Locale::class, MongoLocaleSerializer)
// contextual(Binary::class, BinarySerializer)
}
/**
*
*/
abstract class TemporalExtendedJsonSerializer : KSerializer {
override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor(javaClass.simpleName, PrimitiveKind.STRING)
/**
* Returns the number of milliseconds since January 1, 1970, 00:00:00 GMT
* represented by this Temporal object.
*
* @return the number of milliseconds since January 1, 1970, 00:00:00 GMT
* represented by this date.
*/
abstract fun epochMillis(temporal: T): Long
abstract fun instantiate(date: Long): T
override fun serialize(encoder: Encoder, value: T) {
encoder as BsonEncoder
encoder.encodeDateTime(epochMillis(value))
}
override fun deserialize(decoder: Decoder): T {
return when (decoder) {
is FlexibleDecoder -> {
instantiate(
when (decoder.reader.currentBsonType) {
BsonType.STRING -> decoder.decodeString().toLong()
BsonType.DATE_TIME -> decoder.reader.readDateTime()
BsonType.INT32 -> decoder.decodeInt().toLong()
BsonType.INT64 -> decoder.decodeLong()
BsonType.DOUBLE -> decoder.decodeDouble().toLong()
BsonType.DECIMAL128 -> decoder.reader.readDecimal128().toLong()
BsonType.TIMESTAMP -> TimeUnit.SECONDS.toMillis(decoder.reader.readTimestamp().time.toLong())
else -> throw SerializationException("Unsupported ${decoder.reader.currentBsonType} reading date")
}
)
}
else -> throw SerializationException("Unknown decoder type")
}
}
}
//@Serializer(forClass = Calendar::class)
object MongoCalendarSerializer : TemporalExtendedJsonSerializer() {
override fun epochMillis(temporal: Calendar): Long = temporal.timeInMillis
override fun instantiate(date: Long): Calendar =
Calendar.getInstance(TimeZone.getTimeZone("UTC")).apply {
time = Date(date)
}
}
//@Serializer(forClass = Instant::class)
object MongoInstantSerializer : TemporalExtendedJsonSerializer() {
override fun epochMillis(temporal: Instant): Long = temporal.toEpochMilli()
override fun instantiate(date: Long): Instant = Instant.ofEpochMilli(date)
}
//@Serializer(forClass = LocalDate::class)
object MongoLocalDateSerializer : TemporalExtendedJsonSerializer() {
override fun epochMillis(temporal: LocalDate): Long =
MongoInstantSerializer.epochMillis(temporal.atStartOfDay(ZoneOffset.UTC).toInstant())
override fun instantiate(date: Long): LocalDate =
MongoLocalDateTimeSerializer.instantiate(date).toLocalDate()
}
//@Serializer(forClass = LocalDateTime::class)
object MongoLocalDateTimeSerializer : TemporalExtendedJsonSerializer() {
override fun epochMillis(temporal: LocalDateTime): Long =
MongoInstantSerializer.epochMillis(temporal.atZone(ZoneOffset.UTC).toInstant())
override fun instantiate(date: Long): LocalDateTime =
LocalDateTime.ofInstant(MongoInstantSerializer.instantiate(date), ZoneOffset.UTC)
}
//@Serializer(forClass = LocalTime::class)
object MongoLocalTimeSerializer : TemporalExtendedJsonSerializer() {
override fun epochMillis(temporal: LocalTime): Long =
MongoLocalDateTimeSerializer.epochMillis(temporal.atDate(LocalDate.ofEpochDay(0)))
override fun instantiate(date: Long): LocalTime =
MongoLocalDateTimeSerializer.instantiate(date).toLocalTime()
}
//@Serializer(forClass = Locale::class)
object MongoLocaleSerializer : KSerializer {
override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("LocaleSerializer", PrimitiveKind.STRING)
override fun deserialize(decoder: Decoder): Locale = Locale.forLanguageTag(decoder.decodeString())
override fun serialize(encoder: Encoder, value: Locale) {
encoder.encodeString(value.toLanguageTag())
}
}