Uploaded image for project: 'Java Driver'
  1. Java Driver
  2. JAVA-5342

Can't encode classes with nullable type parameters

    • Type: Icon: Bug Bug
    • Resolution: Unresolved
    • Priority: Icon: Unknown Unknown
    • None
    • Affects Version/s: 4.11.1, 5.0.0
    • Component/s: Kotlin
    • Java Drivers
    • Hide

      1. What would you like to communicate to the user about this feature?
      2. Would you like the user to see examples of the syntax and/or executable code and its output?
      3. Which versions of the driver/connector does this apply to?

      Show
      1. What would you like to communicate to the user about this feature? 2. Would you like the user to see examples of the syntax and/or executable code and its output? 3. Which versions of the driver/connector does this apply to?

      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
       

            Assignee:
            Unassigned Unassigned
            Reporter:
            cliffred.vanvelzen@edsn.nl Cliffred van Velzen
            Votes:
            1 Vote for this issue
            Watchers:
            4 Start watching this issue

              Created:
              Updated: