I'm trying to make a custom serializer for the Color
class using the kmongo-coroutine-serialization
dependency.
I'm getting an exception when doing it saying:
Exception in thread "main" org.bson.BsonInvalidOperationException: readEndDocument can only be called when State is END_OF_DOCUMENT, not when State is VALUE.
Document I test it on as json
{
"_id": {
"$oid": "61fe4f745064370bd1473c41"
},
"id": 1,
"color": "#9ac0db"
}
ExampleDocument
class:
@Serializable
data class ExampleDocument(
@Serializable(with = ColorHexSerializer::class) val color: Color
)
ColorHexSerializer
object:
for testing purposes I always return blue
internal object ColorHexSerializer : KSerializer<Color> {
override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("color_hex", PrimitiveKind.STRING)
override fun serialize(encoder: Encoder, value: Color) {
val hex = String.format("#%06x", value.rgb and 0xFFFFFF)
encoder.encodeString(hex)
}
override fun deserialize(decoder: Decoder): Color {
return Color.BLUE
}
}
main function:
suspend fun main() {
registerSerializer(ColorHexSerializer)
val document =
KMongo.createClient("connectionString")
.getDatabase("database")
.getCollectionOfName<ExampleDocument>("testing")
.find(eq("id", 1))
.awaitFirst()
}
Converting the bson document to json and deserialize it then with kotlinxserialization works just fine. Can anyone help me here?
Thanks in advance
From the documentation of Decoder
:
Deserialization process takes a decoder and asks him for a sequence of primitive elements, defined by a deserializer serial form, while decoder knows how to retrieve these primitive elements from an actual format representations.
and
To be more specific, serialization asks a decoder for a sequence of "give me an int, give me a double, give me a list of strings and give me another object that is a nested int"
You need to specify all the values you read from the decoder in order. All values written also need to be read. It just seems that (at least in your case) kotlinx.serialization
ignores the mistake of leftover content to read while kmongo throws an exception.
By returning the color blue by default, you skip the step of reading the string resulting in the string to be left.
Since there is a String left, the state of the object is VALUE
(there is a value left to read) while you try to finish reading the document.
override fun deserialize(decoder: Decoder): Color {
decoder.decodeString()
return Color.BLUE
}