【问题标题】:Scala pickling case class versioningScala酸洗案例类版本控制
【发布时间】:2014-09-21 15:21:17
【问题描述】:

我希望能够使用 scala 酸洗来存储案例类的二进制表示。

我想知道是否有办法管理案例类的版本控制(协议缓冲区允许这样做的方式)


这是我的例子

我在某个日期制作了一个程序,案例类如下

case class MessageTest(a:String,b:String) 

然后我序列化这个类的一个实例

import scala.pickling._
import binary._
val bytes=MessageTest("1","2").pickle

然后我将结果存储到一个文件中


稍后,我现在可能需要对我的案例类进行改进,以添加一个新的可选字段

case class MessageTest (a:String,b:String,c:Option[String]=None)

我希望能够重用我之前存储在文件中的数据,对其进行反序列化并能够恢复案例类的实例(新参数的默认值)

但是当我使用下面的代码时

import scala.pickling._
import binary._
val messageback=bytes.unpickle[MessageTest]

我收到以下错误:

java.lang.ArrayIndexOutOfBoundsException: 26 在 scala.pickling.binary.BinaryPickleReader$$anonfun$2.apply(BinaryPickleFormat.scala:446) 在 scala.pickling.binary.BinaryPickleReader$$anonfun$2.apply(BinaryPickleFormat.scala:434) 在 scala.pickling.PickleTools$class.withHints(Tools.scala:498) 在 scala.pickling.binary.BinaryPickleReader.withHints(BinaryPickleFormat.scala:425) 在 scala.pickling.binary.BinaryPickleReader.beginEntryNoTagDebug(BinaryPickleFormat.scala:434) 在 scala.pickling.binary.BinaryPickleReader.beginEntryNoTag(BinaryPickleFormat.scala:431)


我是不是做错了什么?

是否有现有的方法可以使我的方案发挥作用?

问候

【问题讨论】:

标签: scala scala-pickling


【解决方案1】:

问题是您试图反序列化回与您序列化的对象不同的对象。

考虑一下。 第一个对象

scala> case class MessageTest(a: String, b:String)
defined class MessageTest

scala> val bytes = MessageTest("a", "b").pickle
bytes: pickling.binary.pickleFormat.PickleType = BinaryPickle([0,0,0,81,36,108,105,110,101,53,49,46,36,114,101,97,100,46,36,105,119,46,36,105,119,46,36,105,119,46,36,105,119,46,36,105,119,46,36,105,119,46,36,105,119,46,36,105,119,46,36,105,119,46,36,105,119,46,36,105,119,46,36,105,119,46,36,105,119,46,36,105,119,46,77,101,115,115,97,103,101,84,101,115,116,0,0,0,1,97,0,0,0,1,98])

现在使用更改后的案例对象...

scala> case class MessageTest(a: String, b: String, c: Option[String] = None)
defined class MessageTest

scala> val bytes = MessageTest("a", "b").pickle
bytes: pickling.binary.pickleFormat.PickleType = BinaryPickle([0,0,0,81,36,108,105,110,101,53,51,46,36,114,101,97,100,46,36,105,119,46,36,105,119,46,36,105,119,46,36,105,119,46,36,105,119,46,36,105,119,46,36,105,119,46,36,105,119,46,36,105,119,46,36,105,119,46,36,105,119,46,36,105,119,46,36,105,119,46,36,105,119,46,77,101,115,115,97,103,101,84,101,115,116,0,0,0,1,97,0,0,0,1,98,0,0,0,15,115,99,97,108,97,46,78,111,110,101,46,116,121,112,101])

在这种情况下,库无法知道您的意思,因为它只是希望签名匹配。

https://github.com/scala/pickling/issues/39 但你至少可以选择一种方式。如此处所示。

import scala.pickling._
import scala.pickling.Defaults._
import scala.pickling.binary._

case class LegacyMessage(a: String, b: String)
case class Message(a: String, b: String, c: Option[String] = None)

implicit val legacyUnpickler = Unpickler.generate[LegacyMessage]
implicit val messageUnpickler = Unpickler.generate[Message]

val legacyBytes = LegacyMessage("a", "b")
val msgBytes = Message("a", "b", None)

val pickledBytes = msgBytes.pickle
val pickledLegacy = legacyBytes.pickle

// New Message can Serialize back to Legacy Messages
val newToOld = pickledBytes.unpickle[LegacyMessage]

// Old Messages can not serialize up to the new message schema
// println(pickledLegacy.unpickle[Message])

val old = pickledLegacy.unpickle[LegacyMessage]

if(newToOld == old){
  println(true)
}

希望这会有所帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-05-29
    • 1970-01-01
    • 1970-01-01
    • 2014-09-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-24
    相关资源
    最近更新 更多