問題的解決方案是在幾個月前發現的。所以我想盡快回答這個問題。 問題在於,由於代碼中的錯誤,該類使用標準的Kryo FieldSerializer序列化,該序列不兼容。 我們必須執行以下操作來反序列化舊類並將其轉換爲新的序列化類。
的情況是:
case class ClassA(field1 : Long, field2 : String)
它連載這樣的:
object ClassASerializer extends Serializer[ClassA] with Serializable{
override def write(kryo: Kryo, output: Output, t: ClassA) = {
output.writeLong { t.field1 }
output.writeString { t.field2 }
}
override def read(kryo: Kryo, input: Input, aClass: Class[ClassA]) =
classA(
field1 = input.readLong(),
field2 = input.readLong()
)
,並與串行序列化包含這些類序列,以註冊所有人的所有序列化是循環類。
protected def registry: Seq[aClass: Class[A], serializer: Serializer[A]] = ...
final def register(kryo: Kryo) = {
registry.foreach { registrable => kryo.register(registrable.aClass, registrable.serializer) }
}
該類需要通過添加一個新字段進行修改,該字段是另一個案例類的實例。
爲了進行這樣的改變,我們不得不使用有關的KRYO庫「可選」的註釋,
...
import com.esotericsoftware.kryo.serializers.FieldSerializer.Optional
import scala.annotation.meta.field
...
case class ClassA(field1 : Long, field2 : String, @(Optional @field)("field3") field3 : ClassB)
串行器被修改,例如讀取舊的序列化的類時,它可以實例字段3用默認值和,寫入時,寫這樣默認值:
object ClassASerializer extends Serializer[ClassA] with Serializable{
override def write(kryo: Kryo, output: Output, t: ClassA) = {
output.writeLong { t.field1 }
output.writeString { t.field2 }
kryo.writeObject(output, Option { t.field3 } getOrElse ClassB.default, ClassBSerializer)
}
override def read(kryo: Kryo, input: Input, aClass: Class[ClassA]) =
ClassA(
field1 = input.readLong(),
field2 = input.readLong(),
field3 = ClassB.default
)
的KRYO串行登記還修改也註冊可選字段:
protected def registry: Seq[aClass: Class[A], serializer: Serializer[A]] = ...
def optionals = Seq("field3")
final def register(kryo: Kryo) = {
optionals.foreach { optional =>
kryo.getContext.asInstanceOf[ObjectMap[Any, Any]].put(optional, true) }
registry.foreach { registrable => kryo.register(registrable.aClass, registrable.serializer) }
}
因此,我們能夠編寫新版本的序列化類。 之後,我們必須刪除可選註釋,修改序列化程序以便從新的序列化類讀取實際字段,並刪除可選的序列化程序註冊並將其添加到註冊表Seq。
與此同時,我們糾正了強制通過FieldSerializer進行序列化的代碼中的錯誤,但這不在問題的範圍之內。