Search code examples
scalaserializationscala.jsupickle

uPickle and ScalaJS: sealed trait serialisation


I'm trying to get a basic upickle example to work and it seems I'm missing something here. I want to try out the example provided on the readme page for upickle

import upickle._

sealed trait A
@key("Bee") case class B(i: Int) extends A
case object C extends A

Then, my code is:

object Model {
  def main(args: Array[String]): Unit = {

    val a = B(5): A
    println(a)

    val out = write(a)
    println(out)

    val a2 = read[A](out)
    println(a2)

    println(a == a2)

  }
}

All I get is the error:

The referenced trait [[A]] does not have any sub-classes. This may happen due to a limitation of scalac (SI-7046) given that the trait is not in the same package. If this is the case, the hierarchy may be defined using integer constants.

I have two questions:

  • How can I convince uPickle that the trait is in the same package? (Because it is.)
  • Or if I can't: how can I define the hierarchy with integer constants?

Solution

  • Ever had the syndrome that you can spend multiple hours on a problem like this, and you solve it minutes after asking the StackOverflow question?

    It turns out that due to compiler-specific details, such a sealed trait won't know its direct subclasses until after the point in the file where it's defined. So, in this case, I had defined the trait and its cases after the main method, where upickle would do its macro expansion and magic. At this point, it won't know about the trait's cases. If the main method is moved in the same file after the definition of the trait and its cases, it will work.