问题的解决方案是在几个月前发现的。所以我想尽快回答这个问题。 问题在于,由于代码中的错误,该类使用标准的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进行序列化的代码中的错误,但这不在问题的范围之内。