Skip to content

Commit 7b76e5e

Browse files
authored
Issue 382 (#537)
1 parent 17f9f5c commit 7b76e5e

File tree

2 files changed

+47
-5
lines changed

2 files changed

+47
-5
lines changed

src/main/scala/com/fasterxml/jackson/module/scala/deser/OptionDeserializerModule.scala

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,18 @@ package com.fasterxml.jackson.module.scala.deser
33
import com.fasterxml.jackson.core.{JsonParser, JsonToken}
44
import com.fasterxml.jackson.databind._
55
import com.fasterxml.jackson.databind.`type`.{ReferenceType, TypeFactory}
6-
import com.fasterxml.jackson.databind.deser.std.StdDeserializer
6+
import com.fasterxml.jackson.databind.deser.std.ReferenceTypeDeserializer
77
import com.fasterxml.jackson.databind.deser.{ContextualDeserializer, Deserializers}
88
import com.fasterxml.jackson.databind.jsontype.TypeDeserializer
99
import com.fasterxml.jackson.module.scala.modifiers.OptionTypeModifierModule
1010

11+
import scala.util.control.NonFatal
12+
1113
private class OptionDeserializer(fullType: JavaType,
1214
valueTypeDeserializer: Option[TypeDeserializer],
1315
valueDeserializer: Option[JsonDeserializer[AnyRef]],
1416
beanProperty: Option[BeanProperty] = None)
15-
extends StdDeserializer[Option[AnyRef]](fullType) with ContextualDeserializer {
17+
extends ReferenceTypeDeserializer[Option[AnyRef]](fullType, valueTypeDeserializer.orNull, valueDeserializer.orNull) with ContextualDeserializer {
1618

1719
override def getValueType: JavaType = fullType
1820

@@ -27,9 +29,10 @@ private class OptionDeserializer(fullType: JavaType,
2729
typeDeser == this.valueTypeDeserializer &&
2830
valueDeser == this.valueDeserializer &&
2931
beanProperty == this.beanProperty) {
30-
return this
32+
this
33+
} else {
34+
new OptionDeserializer(fullType, typeDeser, valueDeser.asInstanceOf[Option[JsonDeserializer[AnyRef]]], beanProperty)
3135
}
32-
new OptionDeserializer(fullType, typeDeser, valueDeser.asInstanceOf[Option[JsonDeserializer[AnyRef]]], beanProperty)
3336
}
3437

3538
override def createContextual(ctxt: DeserializationContext, property: BeanProperty): JsonDeserializer[Option[AnyRef]] = {
@@ -69,9 +72,32 @@ private class OptionDeserializer(fullType: JavaType,
6972
if (t == JsonToken.VALUE_NULL) {
7073
getNullValue(ctxt)
7174
} else {
72-
typeDeserializer.deserializeTypedFromAny(jp, ctxt).asInstanceOf[Option[AnyRef]]
75+
valueTypeDeserializer match {
76+
case Some(vtd) => Option(vtd.deserializeTypedFromAny(jp, ctxt))
77+
case _ => {
78+
typeDeserializer.deserializeTypedFromAny(jp, ctxt) match {
79+
case Some(any) => referenceValue(any)
80+
case any => referenceValue(any)
81+
}
82+
}
83+
}
7384
}
7485
}
86+
87+
override def referenceValue(contents: Any): Option[AnyRef] = {
88+
Option(contents) match {
89+
case Some(anyRef: AnyRef) => Some(anyRef)
90+
case _ => None
91+
}
92+
}
93+
94+
override def withResolved(typeDeser: TypeDeserializer, valueDeser: JsonDeserializer[_]): ReferenceTypeDeserializer[Option[AnyRef]] = {
95+
new OptionDeserializer(fullType, Some(typeDeser), valueDeser.asInstanceOf[Option[JsonDeserializer[AnyRef]]], beanProperty)
96+
}
97+
98+
override def updateReference(reference: Option[AnyRef], contents: Any): Option[AnyRef] = referenceValue(contents)
99+
100+
override def getReferenced(reference: Option[AnyRef]): AnyRef = reference.orNull
75101
}
76102

77103
private object OptionDeserializerResolver extends Deserializers.Base {

src/test/scala/com/fasterxml/jackson/module/scala/deser/OptionDeserializerTest.scala

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,10 @@ object OptionDeserializerTest {
3333

3434
case class Foo(bar: String)
3535
case class Wrapper[T](t: T)
36+
37+
trait Marker
38+
case class AMarker(a: Int) extends Marker
39+
case class XMarker(x: Option[Marker])
3640
}
3741

3842
class OptionDeserializerTest extends DeserializerTest {
@@ -98,4 +102,16 @@ class OptionDeserializerTest extends DeserializerTest {
98102
val result2 = mapper.readValue(json, classOf[OptionWrapper])
99103
result2 shouldEqual OptionWrapper(None)
100104
}
105+
106+
//https://github.com/FasterXML/jackson-module-scala/issues/382
107+
it should "handle generics" in {
108+
val mapper = new ObjectMapper
109+
mapper.registerModule(DefaultScalaModule)
110+
mapper.enableDefaultTypingAsProperty(ObjectMapper.DefaultTyping.OBJECT_AND_NON_CONCRETE, "_t")
111+
val v = XMarker(Some(AMarker(1)))
112+
val str = mapper.writeValueAsString(v)
113+
println(str) // 1
114+
val d = mapper.readValue(str, classOf[XMarker]) // 2
115+
println(d)
116+
}
101117
}

0 commit comments

Comments
 (0)