Summary
Encoding an object that contains a property that has a nullable generic parameter type, like Container in the example below will fail with
org.bson.BsonInvalidOperationException: writeString can only be called when State is VALUE, not when State is NAME
or
org.bson.BsonInvalidOperationException: writeNull can only be called when State is VALUE, not when State is NAME
depending on whether the actual value is null.
How to Reproduce
@Serializable data class Box<T>( val boxed: T ) @Serializable data class Container( // Using a nullable generic causes the exception, Box<String> works fine val box: Box<String?> ) fun main() { KotlinSerializerCodec.create<Container>()!!.encode( JsonWriter(StringWriter()), Container(Box("foo")), EncoderContext.builder().build() ) }
run this results in
Exception in thread "main" org.bson.BsonInvalidOperationException: writeString can only be called when State is VALUE, not when State is NAME at org.bson.AbstractBsonWriter.throwInvalidState(AbstractBsonWriter.java:747) at org.bson.AbstractBsonWriter.checkPreconditions(AbstractBsonWriter.java:702) at org.bson.AbstractBsonWriter.writeString(AbstractBsonWriter.java:607) at org.bson.codecs.kotlinx.DefaultBsonEncoder.encodeString(BsonEncoder.kt:166) at kotlinx.serialization.internal.StringSerializer.serialize(Primitives.kt:159) at kotlinx.serialization.internal.StringSerializer.serialize(Primitives.kt:156) at kotlinx.serialization.encoding.Encoder$DefaultImpls.encodeSerializableValue(Encoding.kt:279) at kotlinx.serialization.encoding.AbstractEncoder.encodeSerializableValue(AbstractEncoder.kt:18) at kotlinx.serialization.internal.NullableSerializer.serialize(NullableSerializer.kt:23) at kotlinx.serialization.encoding.Encoder$DefaultImpls.encodeSerializableValue(Encoding.kt:279) at kotlinx.serialization.encoding.AbstractEncoder.encodeSerializableValue(AbstractEncoder.kt:18) at kotlinx.serialization.encoding.AbstractEncoder.encodeSerializableElement(AbstractEncoder.kt:80) at org.example.Box.write$Self$a(Test.kt:14)
Notice that
org.example.Box.write$Self$a calls encodeSerializableElement instead of
encodeNullableSerializableElement, which might indicate a bug in the kotlinx serialization compiler plugin.
I've already created a fix for this: https://github.com/mongodb/mongo-java-driver/pull/1317