2014-09-21 10 views
10

Ich würde gerne Scala Beizen verwenden, um binäre Darstellung einer Fallklasse zu speichern.Scala Beizen Fall Klasse Versionierung

Ich möchte wissen, ob es einen Weg gibt, Versionierung von Fallklasse zu verwalten (die Art und Weise Protokollpuffer erlaubt zu tun)


Hier ist mein Beispiel

Ich mache ein Programm bei bestimmte Datum, mit der folgenden Fall Klasse

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

Dann serialisiert ich eine Instanz dieser Klasse

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

Und dann speichere ich das Ergebnis in eine Datei


Später könnte ich jetzt Evolution auf meinem Fall Klasse machen müssen, ein neues optionales Feld

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

ich hinzufügen Ich möchte die Daten, die ich zuvor in meiner Datei gespeichert hatte, wiederverwenden und die Instanz einer Fallklasse wiederherstellen können (mit dem Standardwert für den neuen Parameter)

Aber wenn ich den folgenden Code verwenden

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

Ich habe folgende Fehlermeldung:

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


Habe ich etwas falsch gemacht?

Gibt es einen bestehenden Weg, um mein Szenario arbeiten zu lassen?

Grüße

+0

Was für eine Stille ... Ich habe die gleiche Frage, @Fred hast du eine Lösung gefunden? – Emer

+0

Wir erwägen, den Typ "Map" als Workaround zu verwenden. http://docs.scala-lang.org/overviews/collections/maps – Emer

Antwort

0

Nun das Problem ist, dass Sie versuchen, auf ein anderes Objekt deserialisieren zurück als das, was Sie serialisiert.

Betrachten Sie dies. Das erste Objekt

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

nun mit dem geänderten Fall Objekt ...

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

Es gibt keine Möglichkeit, die Bibliothek wissen, was Sie in diesem Fall bedeuten, weil es nur Unterschriften erwartet bis entsprechen.

https://github.com/scala/pickling/issues/39 aber Sie können zumindest einen Weg damit gehen. wie hier gezeigt.

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

Hoffentlich hilft das ein wenig.