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

bson-kotlinx BsonEncoder.encodeNullableSerializableValue does not always reset deferredElementName

    • Type: Icon: Bug Bug
    • Resolution: Fixed
    • Priority: Icon: Major - P3 Major - P3
    • 4.11.3, 5.1.4, 5.2.0
    • Affects Version/s: None
    • Component/s: None
    • None
    • Java Drivers
    • Not Needed
    • 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?

      When the value is null and we do not have explicitNulls = true, the deferred element is not written so the deferredElementName should be cleared.  The 
      encodeSerializableValue method does this, but 
      encodeNullableSerializableValue does not.  This leads to the an error when trying to encode the next element.
       
      Example

      @Serializable
      data class Doc(
          val elements: List<Element>
      )
      
      @Serializable
      data class Element(
          val required: String,
          val optional: String? = null,
      )
      
      fun main() {
          val doc = Doc(listOf(Element(required = "some value"), Element(required = "some other value")))
      
          println("This is the workaround - it works")
          KotlinSerializerCodec.create<Doc>(bsonConfiguration = BsonConfiguration(explicitNulls = true))!!
              .encode(BsonBinaryWriter(BasicOutputBuffer()), doc, EncoderContext.builder().build())
      
          println("This fails")
          KotlinSerializerCodec.create<Doc>()!!
              .encode(BsonBinaryWriter(BasicOutputBuffer()), doc, EncoderContext.builder().build())
      }
      
      

      Output:
       

      This is the workaround - it works
      This fails
      Exception in thread "main" org.bson.BsonInvalidOperationException: WriteName can only be called when State is NAME, not when State is VALUE
          at org.bson.AbstractBsonWriter.throwInvalidState(AbstractBsonWriter.java:747)
          at org.bson.AbstractBsonWriter.writeName(AbstractBsonWriter.java:531)
          at org.bson.codecs.kotlinx.DefaultBsonEncoder.encodeName(BsonEncoder.kt:208)
          at org.bson.codecs.kotlinx.DefaultBsonEncoder.encodeSerializableValue(BsonEncoder.kt:145)
          at kotlinx.serialization.encoding.AbstractEncoder.encodeSerializableElement(AbstractEncoder.kt:80)
          at kotlinx.serialization.internal.CollectionLikeSerializer.serialize(CollectionSerializers.kt:69)
          at kotlinx.serialization.encoding.Encoder$DefaultImpls.encodeSerializableValue(Encoding.kt:279)
          at kotlinx.serialization.encoding.AbstractEncoder.encodeSerializableValue(AbstractEncoder.kt:18)
          at org.bson.codecs.kotlinx.DefaultBsonEncoder.encodeSerializableValue(BsonEncoder.kt:151)
          at kotlinx.serialization.encoding.AbstractEncoder.encodeSerializableElement(AbstractEncoder.kt:80) 

       

            Assignee:
            ross@mongodb.com Ross Lawley
            Reporter:
            mark.rodgers@cadenza.co.nz Mark Rodgers
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated:
              Resolved: