-
-
Notifications
You must be signed in to change notification settings - Fork 143
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Jackson doesn't invoke default constructor of a case class on deserialization #330
Comments
Here is another example that should be related to this issue (version 2.8.9):
The serialized JSON is Deserialization sometimes succeeds and sometimes fails with
|
In 2.9.4, this issue is causing me headaches. I also have code that spuriously fails converting JSON to a case class. I believe it is because the order of constructors returned in Running this code produces a different ordering on each invocation:
When the JVM gods decide to order my constructors in a way that the "right" one is at the top, things work correctly. The
|
seems similar to #159 |
I've added a possible fix in v2.12.2 |
Jackson version 2.8.9, 2.8.6:
Say, the following case class is defined:
case class Result(data: Seq[Int] = Seq.empty) { def this() = this(Seq(1)) }
Then, if we write the following test:
It will fail in a few runs because deserialized.data would equal to null.
The root cause is the:
com.fasterxml.jackson.module.scala.introspect.BeanIntrospector#def findConstructorParam(c: Class[_], name: String): Option[ConstructorParameter]
This method resolves
val primaryConstructor = c.getConstructors.headOption
If
primaryConstructor
is resolved to a default constructor with no arguments, then findConstructorParam will eventually return None. If None is returned,BeanDeserializerBase._vanillaProcessing
will eventually be set to true, this will make Jackson call the default constructor of Result.But, if the
primaryConstructor
is resolved to the constructor with the argument, then findConstructorParam will return Some(), which eventually leads Jackson to ignore the default constructor.The
primaryConstructor
resolution should be changed to something like:c.getConstructors.find(findADefaultConstructor).orElse(c.getConstructors.headOption)
Note:
The issue of not calling the default constructor can be eliminated by annotating it with @JsonCreator as follows:
case class Result(data: Seq[Int] = Seq.empty) { @JsonCreator def this() = this(Seq(1)) }
The text was updated successfully, but these errors were encountered: