On Mon, Oct 22, 2018 at 9:55 AM lev <[email protected]> wrote:
>
> I posted this question on SO, but it didn't get much attention, so I'm 
> posting here as well.
>
> -----
>
>
> I'd like to deserialize the following class:
>
> case class Target(
>                    a: Option[Long],
>                    b: String
>                  )
>
> while providing a custom initial value for missing fields.
>
>
> I'm using this mixin to overcome this bug: 
> https://github.com/FasterXML/jackson-module-scala/wiki/FAQ#deserializing-optionint-and-other-primitive-challenges
>
>
> trait Mixin {
>    @JsonDeserialize(contentAs = classOf[Long]) def a: Option[Long]
> }
>
>
> and I'm using this ValueInstantiator to provide a custom initial value:
>
> class TargetInstantiator extends ValueInstantiator{
>   override def canCreateUsingDefault: Boolean = true
>
>   override def createUsingDefault(ctxt: DeserializationContext): AnyRef = {
>     Target(Some(1), "bbb")
>   }
> }
>
>
> the mixing and the instantiator work well on their own, but when I combine 
> the 2 together, the mixin doesn't seem to have any effect
>
>
> here is the full code:
>
> case class Target(
>                    a: Option[Long],
>                    b: String
>                  )
> trait Mixin {
>   @JsonDeserialize(contentAs = classOf[Long]) def a: Option[Long]
> }
>
> class TargetInstantiator extends ValueInstantiator{
>   override def canCreateUsingDefault: Boolean = true
>
>   override def createUsingDefault(ctxt: DeserializationContext): AnyRef = {
>     Target(Some(1), "bbb")
>   }
> }
>
>
> val svi = new SimpleValueInstantiators()
> svi.addValueInstantiator(classOf[Target], new TargetInstantiator)
>
> val module = new SimpleModule("MyModule")
> module.setValueInstantiators(svi)
>
> val mapper = new ObjectMapper()
>   .registerModule(DefaultScalaModule)
>   .registerModule(module)
>   .addMixIn(classOf[Target], classOf[Mixin])
> val req =
>   """{
>     |  "a": 123
>     |}
>   """.stripMargin
> val res = mapper.readValue(req, classOf[Target])
> println(res.a.map(_ + 1)) //should print Some(124)
> println(res.b) //should print "bbb"
>
> the above code would fail with the error
>
> java.lang.Integer cannot be cast to java.lang.Long
>
> on the first print.
>
>
> if I comment out .registerModule(module), and add "b" to the json string, the 
> code would work.
>
>
> Is it possible to make the mixin and the instantiator work together?

At high level, yes, mix-ins and ValueInstantiator can and should be
able to co-exist.
But I guess question is more about ValueInstantiator and `contentAs`
annotation via mix-ins.
Use of mix-ins, in itself, is invisible to most code in Jackson and
would be behave same as if annotation
was directly used in target class.

Challenge here is mostly, I think, that this is for Scala, and Scala
module is both lagging behind with some features (partly since I don't
know Scala enough to help much with the module) and also uses some of
the facilities to support Scala features. I don't know for sure but it
might actually use ValueInstantiators of its own.

So one thing that is often done to troubleshoot is to see if there is
Java-only reproduction of the issue; if so, it can be worked on
jackson-databind.
If not, it is likely problem with Scala module's handling of things.

-+ Tatu +-

-- 
You received this message because you are subscribed to the Google Groups 
"jackson-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to