我希望能够使用scala pickle来存储case类的二进制表示。
我想知道是否有一种方法来管理案例类的版本控制(协议缓冲区允许的方式)
这是我的示例
我在某个日期制作了一个程序,使用以下案例类
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.pickle.binary.BinaryPickleReader$$anonfun$2.apply(BinaryPickleFormat.scala:446)在scala.pickle.binary.BinaryPickleReader$$anonfun$2.apply(BinaryPickleFormat.scala:434)在scala.pickle.PickleTools$class.withHints(Tools.scala:498)在scala.pickle.binary.BinaryPickleReader.withHints(BinaryPickleFormat.scala:425)在scala.pickle.binary.BinaryPickleReader.beginEntryNoTagDebug(BinaryPickleFormat.scala:434)在scala.pickle.binary.BinaryPickleReader.beginEntryNoTag(BinaryPickleFormat.scala:431)
我做错什么了吗?
有没有一种现有的方法可以让我的场景发挥作用?
问候
问题是,您正试图反序列化回与序列化到的对象不同的对象。
想想这个。第一个对象
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])
现在有了更改后的case对象。。。
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)
}
希望这能有所帮助。