Skip to content

Cannot deserialize None values in a tuple #628

@negokaz

Description

@negokaz

Deserializing a tuple that contains Some values succeeds.
However, a MismatchedInputException will be thrown during deserialization If the tuple contains None values.

Version

  • Scala 2.13.6
  • jackson-databind 2.12.3
  • jackson-module-scala 2.12.3

Actual behavior

The test case "deserialize OptionalTupleHolder that has 'None' values" fails.

package com.example

import com.fasterxml.jackson.databind.json.JsonMapper
import com.fasterxml.jackson.module.scala.DefaultScalaModule
import org.scalatest.funsuite.AnyFunSuite
import org.scalatest.matchers.should.Matchers

object JacksonScalaSpec {
  final case class OptionalTupleHolder(tuple: (Option[Int], Option[String]))
}

class JacksonScalaSpec extends AnyFunSuite with Matchers {
  import JacksonScalaSpec._

  private val mapper =
    JsonMapper
      .builder()
      .addModule(DefaultScalaModule)
      .build()

  println(mapper.version())

  test("deserialize OptionalTupleHolder that has 'Some' values") {
    val obj  = OptionalTupleHolder((Option(1), Option("2")))
    val json = mapper.writeValueAsString(obj)
    println(json) // {"tuple":[1,"2"]}
    val deserialized = mapper.reyadValue(json, classOf[OptionalTupleHolder])
    println(deserialized)

    obj should be(deserialized)
    // pass
  }

  test("deserialize OptionalTupleHolder that has 'None' values") {
    val obj  = OptionalTupleHolder((Option.empty, Option.empty))
    val json = mapper.writeValueAsString(obj)
    println(json) // {"tuple":[null,null]}
    val deserialized = mapper.readValue(json, classOf[OptionalTupleHolder])
    // throws com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize value of type `java.lang.String` from Null value (token `JsonToken.VALUE_NULL`)
    println(deserialized)

    obj should be(deserialized)
  }
}

Details of MismatchedInputException

Cannot deserialize value of type `java.lang.String` from Null value (token `JsonToken.VALUE_NULL`)
 at [Source: (String)"{"tuple":[null,null]}"; line: 1, column: 16] (through reference chain: com.example.JacksonScalaSpec$OptionalTupleHolder["tuple"])
com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize value of type `java.lang.String` from Null value (token `JsonToken.VALUE_NULL`)
 at [Source: (String)"{"tuple":[null,null]}"; line: 1, column: 16] (through reference chain: com.example.JacksonScalaSpec$OptionalTupleHolder["tuple"])
	at com.fasterxml.jackson.databind.exc.MismatchedInputException.from(MismatchedInputException.java:59)
	at com.fasterxml.jackson.databind.DeserializationContext.reportInputMismatch(DeserializationContext.java:1601)
	at com.fasterxml.jackson.databind.DeserializationContext.handleUnexpectedToken(DeserializationContext.java:1375)
	at com.fasterxml.jackson.databind.DeserializationContext.handleUnexpectedToken(DeserializationContext.java:1280)
	at com.fasterxml.jackson.databind.deser.std.StringDeserializer.deserialize(StringDeserializer.java:73)
	at com.fasterxml.jackson.databind.deser.std.StringDeserializer.deserialize(StringDeserializer.java:11)
	at com.fasterxml.jackson.module.scala.deser.OptionDeserializer.deserialize(OptionDeserializerModule.scala:61)
	at com.fasterxml.jackson.module.scala.deser.OptionDeserializer.deserialize(OptionDeserializerModule.scala:11)
	at com.fasterxml.jackson.module.scala.deser.TupleDeserializer.$anonfun$deserialize$1(TupleDeserializerModule.scala:48)
	at scala.collection.immutable.Vector1.map(Vector.scala:1886)
	at scala.collection.immutable.Vector1.map(Vector.scala:375)
	at com.fasterxml.jackson.module.scala.deser.TupleDeserializer.deserialize(TupleDeserializerModule.scala:45)
	at com.fasterxml.jackson.module.scala.deser.TupleDeserializer.deserialize(TupleDeserializerModule.scala:10)
	at com.fasterxml.jackson.databind.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:542)
	at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeWithErrorWrapping(BeanDeserializer.java:565)
	at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeUsingPropertyBased(BeanDeserializer.java:449)
	at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromObjectUsingNonDefault(BeanDeserializerBase.java:1405)
	at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:362)
	at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:195)
	at com.fasterxml.jackson.databind.deser.DefaultDeserializationContext.readRootValue(DefaultDeserializationContext.java:322)
	at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4593)
	at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3548)
	at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3516)
	at com.example.JacksonScalaSpec.$anonfun$new$2(JacksonScalaSpec.scala:38)

Expected behavior

The json {"tuple":[null,null]} is deserialized to OptionalTupleHolder((None, None)) without any Exceptions.

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions