uPickle 和 ScalaJS:密封特征序列化

uPickle and ScalaJS: sealed trait serialisation

我正在尝试让一个基本的泡菜示例起作用,但似乎我在这里遗漏了一些东西。我想尝试 the readme page for upickle

上提供的示例
import upickle._

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

那么,我的代码是:

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)

  }
}

我得到的只是错误:

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.

我有两个问题:

你是否曾经有过这样的综合症,你可以在这样的问题上花费多个小时,而你在提出 Whosebug 问题后几分钟就解决了这个问题?

事实证明,由于 compiler-specific details,这种密封特征直到在文件中定义它的位置之后才会知道它的直接子类。因此,在这种情况下,我在 main 方法 之后定义了特征及其案例 ,其中 upickle 将执行其宏扩展和魔术。此时,它不会知道该特征的案例。如果将 main 方法移动到同一个文件中,然后再定义 trait 及其 cases,它将起作用。

我在一个 Scala.js 项目中遇到了这个错误,我在该项目中在服务器和客户端之间共享了一个密封的摘要 class。

解决方案是使用 Typelevel compiler 而不是默认的 Lightbend。

这很容易做到:

  1. 将此放入您的 build.propertiessbt.version=0.13.13-M1
  2. 这在您 build.sbt 的顶部:scalaOrganization in ThisBuild:= "org.typelevel"

为了完整起见,这是 class 我现在可以在客户端和服务器之间共享:

sealed abstract class ServerResponse

case class Ok(msg: String) extends ServerResponse

case class Failure(msg: String) extends ServerResponse