Scala pickling case class versioning -
i able use scala pickling in order store binary representation of case class.
i know if there way manage versioning of case class (the way protocol buffer allows do)
here example
i make program @ date, following case class
case class messagetest(a:string,b:string)
then serialize instance of class
import scala.pickling._ import binary._ val bytes=messagetest("1","2").pickle
and store result file
later on, might have make evolution on case class, add new optional field
case class messagetest (a:string,b:string,c:option[string]=none)
i able reuse data stored in file , deserialize , able recover instance of case class (with default value new parameter)
but when use following code
import scala.pickling._ import binary._ val messageback=bytes.unpickle[messagetest]
i got following error :
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)
did wrong ?
is there existing way make scenario work ?
regards
well problem trying deserialize different object serialized to.
consider this. first object
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])
now changed case object...
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])
there no way library can know mean in case because it's expecting signatures match up.
https://github.com/scala/pickling/issues/39 can @ least go 1 way it. demonstrated here.
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 legacy messages val newtoold = pickledbytes.unpickle[legacymessage] // old messages can not serialize new message schema // println(pickledlegacy.unpickle[message]) val old = pickledlegacy.unpickle[legacymessage] if(newtoold == old){ println(true) }
hopefully helps little.
Comments
Post a Comment