uPickle和ScalaJS:密封特质序列化

8

我正试图让一个基本的upickle示例工作起来,但我似乎漏掉了一些东西。我想尝试一下在upickle的readme页面提供的示例。

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]]没有任何子类。这可能是由于scalac(SI-7046)的限制,因为该特征不在同一个包中所致。如果是这种情况,则可以使用整数常量来定义层次结构。
我的两个问题是:
1.如何说服uPickle特征与在同一个包中?(因为它是。)
2.或者如果我不能:如何使用整数常量定义层次结构?
2个回答

8
你是否曾经遇到过这种情况:你花费了数小时来解决一个问题,但只需要在StackOverflow上提问几分钟就能找到答案?
事实证明,由于编译器特定的细节,这样一个封闭的特质在定义时无法知道其直接子类,直到文件中定义它的点之后。因此,在这种情况下,我在主方法之后定义了特质和其案例,在此时,upickle将执行其宏扩展和魔法,但此时它不会知道特质的案例。如果将主方法移动到同一文件中特质及其案例的定义之后,则可以解决该问题。

1
我的代码在我重命名了特质/子类所在的包之前一直运行良好。由于某种原因,它们必须以不同的顺序编译。我当时真的很困惑。感谢您的帮助。 - Mike McFarland

2
我在一个Scala.js项目中遇到了这个错误,在该项目中我在客户端和服务器之间共享了一个密封抽象类。
解决方案是使用Typelevel编译器,而不是默认的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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接