2014-09-21 2 views
10

Я хотел бы иметь возможность использовать травление scala для хранения двоичного представления класса case.Scala caseing class versioning

Я хотел бы знать, если есть способ управления версиями случае класса (буфер пути протокола позволяет сделать)


Вот мой пример

Я делаю программу на определенная дата, со следующим классом случае

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) 

I хотел бы иметь возможность повторно использовать данные, которые я сохранил ранее в своем файле, для десериализации и восстановления экземпляра класса case (со значением по умолчанию для нового параметра)

Но когда я использую следующий код

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

я получил следующее сообщение об ошибке:

java.lang.ArrayIndexOutOfBoundsException: 26 в scala.pickling.binary.BinaryPickleReader $$ anonfun $ 2.Apply (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

+0

Мы рассматриваем возможность использования типа «Карта» в качестве обходного пути. http://docs.scala-lang.org/overviews/collections/maps – Emer

ответ

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

Надеюсь, это немного поможет.