Skip to content

Commit

Permalink
handle null pointer issue
Browse files Browse the repository at this point in the history
  • Loading branch information
PJ Fanning committed Mar 29, 2020
1 parent 71f534a commit 7ce96a6
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -123,22 +123,26 @@ object ScalaAnnotationIntrospector extends NopAnnotationIntrospector with ValueI

class ScalaValueInstantiator(delegate: StdValueInstantiator, config: DeserializationConfig, descriptor: BeanDescriptor) extends StdValueInstantiator(delegate) {

private val overriddenConstructorArguments = {
private val overriddenConstructorArguments: Array[SettableBeanProperty] = {
val args = delegate.getFromObjectArguments(config)

args.map {
case creator: CreatorProperty =>
// Locate the constructor param that matches it
descriptor.properties.find(_.param.exists(_.index == creator.getCreatorIndex)) match {
case Some(PropertyDescriptor(name, Some(ConstructorParameter(_, _, Some(defaultValue))), _, _, _, _, _)) =>
creator.withNullProvider(new NullValueProvider {
override def getNullValue(ctxt: DeserializationContext): AnyRef = defaultValue()

override def getNullAccessPattern: AccessPattern = AccessPattern.DYNAMIC
})
case _ => creator
Option(args) match {
case Some(array) => {
array.map {
case creator: CreatorProperty =>
// Locate the constructor param that matches it
descriptor.properties.find(_.param.exists(_.index == creator.getCreatorIndex)) match {
case Some(PropertyDescriptor(name, Some(ConstructorParameter(_, _, Some(defaultValue))), _, _, _, _, _)) =>
creator.withNullProvider(new NullValueProvider {
override def getNullValue(ctxt: DeserializationContext): AnyRef = defaultValue()

override def getNullAccessPattern: AccessPattern = AccessPattern.DYNAMIC
})
case _ => creator
}
case other => other
}
case other => other
}
case _ => Array.empty
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,17 @@ object CreatorTest
}
}

sealed abstract class Struct1(val name: String, val classifier: String = "my_default_string") {
override def toString: String = name
}

case class ConstructorWithDefaultValues(s: String = "some string", i: Int = 10, dummy: String)

case class ConstructorWithOptionDefaultValues(s: Option[String] = None, i: Option[Int] = None, dummy: String)

case class ConstructorWithOptionSeqDefaultValues(s: Option[Seq[String]] = None)

case class ConstructorWithOptionStruct(s: Option[Struct1] = None)
}


Expand Down Expand Up @@ -140,4 +146,12 @@ class CreatorTest extends DeserializationFixture {
deser2.s shouldEqual Some(Seq("a", "b"))
f.writeValueAsString(ConstructorWithOptionSeqDefaultValues()) shouldEqual """{"s":null}"""
}

it should "support optional structs with default values" ignore { f =>
val deser = f.readValue[ConstructorWithOptionStruct]("""{}""")
deser.s shouldBe empty
val deser2 = f.readValue[ConstructorWithOptionStruct]("""{"s":{"name":"name"}}""")
deser2.s shouldEqual Some(new Struct1("name"){})
f.writeValueAsString(ConstructorWithOptionStruct()) shouldEqual """{"s":null}"""
}
}

0 comments on commit 7ce96a6

Please sign in to comment.