All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.lightningkite.lightningserver.serialization.BsonOverrides.kt Maven / Gradle / Ivy

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())
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy