Skip to content

Case class deserialized as Map2 for unusual path-dependent types #366

Open
@OndrejSpanel

Description

@OndrejSpanel

Deserialization fails in an unexpected way in following code. No exception is thrown, however from field of Container is deserialized as Map instead of XY, the program outputs:

Container(Map(x -> 0.0, y -> 0.0))

package my.jackpack

import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.module.scala.DefaultScalaModule
import com.fasterxml.jackson.module.scala.experimental.ScalaObjectMapper

case class XY(x: Double = 0, y: Double = 0)

trait Abstract {
  type Vector2f

  trait ConstructVector2f {
    def apply(x: Double, y: Double): Vector2f
  }
  implicit val Vector2f: ConstructVector2f
}

object Concrete extends Abstract {
  type Vector2f = XY
  object Vector2f extends ConstructVector2f {
    def apply(x: Double, y: Double) = XY(x, y)
  }
}

object Abstract {
  val Link: Abstract = Concrete
}

import Abstract.Link.Vector2f

case class Container(from: Vector2f)

object Main extends App {

  val mapper = new ObjectMapper with ScalaObjectMapper

  mapper.registerModule(DefaultScalaModule)

  val input = Container(Vector2f(0,0))

  val out = mapper.writeValueAsString(input)

  val loaded = mapper.readValue[Container](out)

  val xy: Vector2f = loaded.from

  println(loaded) // prints "Container(Map(x -> 0.0, y -> 0.0))" instead of "Container(XY(0.0,0.0))"
  assert(xy.isInstanceOf[XY]) // fails
}

This happens only if the Vector2f is used as import Abstract.Link.Vector2f. Once you change it to Concrete.Vector2f it works fine.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions