2014-09-21 17 views
10

Mi piacerebbe poter utilizzare il serial pickling per memorizzare la rappresentazione binaria di una classe di case.Versioning case class di decapaggio Scala

Vorrei sapere se c'è un modo per gestire il controllo delle versioni di classe caso (il buffer protocollo modo permette di fare)


Ecco il mio esempio

Faccio un programma a una certa data, con la seguente classe case

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

Poi serializzare un'istanza di questa classe

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

E poi salvare il risultato in un file


Più tardi, potrei ora devono fare evoluzione sulla mia classe caso, per aggiungere un nuovo campo facoltativo

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

I vorrebbe essere in grado di riutilizzare i dati che ho archiviato in precedenza nel mio file, per deserializzare ed essere in grado di recuperare un'istanza di una classe case (con valore predefinito per il nuovo parametro)

Ma quando io uso il seguente codice

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

ho ottenuto il seguente errore:

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


ho fatto qualcosa di sbagliato?

Esiste un modo per far funzionare il mio scenario?

saluti

+0

Che silenzio ... Ho la stessa domanda, @Fred hai trovato una soluzione? – Emer

+0

Stiamo considerando di utilizzare il tipo di 'Mappa' come soluzione alternativa. http://docs.scala-lang.org/overviews/collections/maps – Emer

risposta

0

Ebbene il problema è che si sta cercando di deserializzare indietro a un oggetto diverso da quello che serializzato a.

Considerate questo. Il primo oggetto

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

Ora con l'oggetto caso modificato ...

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

Non c'è modo in cui la libreria può sapere cosa vuoi dire in questo caso perché è solo in attesa di firme per abbinare.

https://github.com/scala/pickling/issues/39 ma si può almeno andare in un senso. come dimostrato qui.

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

Speriamo che questo aiuti un po '.

Problemi correlati