uPickle和ScalaJS:密封特征序列化



我正在尝试让一个基本的upickle示例发挥作用,但这里似乎缺少了一些东西。我想试用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)
  }
}

我得到的只是错误:

引用的特征[[A]]没有任何子类。这可能由于标量(SI-7046)的限制而发生不在同一个包中。如果是这种情况,层次结构可能是使用整数常量定义。

我有两个问题:

  • 我如何才能说服uPickle该特性在同一个包中?(因为确实如此。)
  • 或者,如果我不能:我如何用整数常量定义层次结构

是否有过这样的综合征:你可以在这样的问题上花几个小时,并且在问StackOverflow问题几分钟后就解决了?

事实证明,由于编译器特定的细节,这样一个密封的特性直到在文件中定义它的点之后才知道它的直接子类。因此,在这种情况下,我在主要方法之后定义了特性及其情况,upickle将在其中进行宏观扩展和魔术。在这一点上,它不会知道该特征的情况。如果在定义了特征及其事例之后,将主方法移到同一个文件中,它就会起作用。

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

解决方案是使用类型级编译器,而不是默认的Lightbend编译器。

这很容易做到:

  1. 把这个放在你的build.properties:sbt.version=0.13.13-M1
  2. 这个在你的build.sbt:scalaOrganization in ThisBuild:= "org.typelevel"的顶部

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

sealed abstract class ServerResponse
case class Ok(msg: String) extends ServerResponse
case class Failure(msg: String) extends ServerResponse

最新更新