2014-09-21 161 views
10

我希望能够使用斯卡拉酸洗为了存储案例类的二进制表示。斯卡拉酸洗案例类版本

我想知道是否有管理案例类(单向协议缓冲区允许这样做)


这里是我的榜样

我做一个程序在版本管理办法某日,有下列情形类

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.适用(BinaryPickleFormat .scala:446) at scala.pickling.binary.BinaryPickleReader $$ anonfun $ 2.apply(BinaryPickleFormat.scala:434) at scala.pickling.PickleTools $ class.withHints(Tools.scala:498) at scala.pickling .binary.BinaryPickleReader.withHints(BinaryPickleFormat.scala:425) at scala.pickling.binary.BinaryPickleReader.beginEntryNoTagDebug(BinaryPickleFormat.scala:434) 在scala.pickling.binary.BinaryPickleReader.beginEntryNoTag(BinaryPickleFormat.scala:431)


难道我做错了什么?

有没有现成的方法来使我的方案工作?

问候

+0

沉默......我有同样的问题,@Fred找到了解决方案吗? – Emer 2016-02-23 11:54:28

+0

我们正在考虑使用'Map'类型作为解决方法。 http://docs.scala-lang.org/overviews/collections/maps – Emer 2016-02-23 12:06:26

回答

0

那么问题是,你正在尝试反序列化回不同的对象比你序列化到。

请考虑这一点。 第一个对象

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) 
} 

希望这会有所帮助。