2014-09-21 138 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) 
} 

希望這會有所幫助。