0

我想使用 upickle 实现一个 akka 序列化器,但我不确定它是否可能。为此,我需要实现类似以下的序列化器:

import akka.serialization.Serializer
import upickle.default._

class UpickleSerializer extends Serializer {

    def includeManifest: Boolean = true
    def identifier = 1234567

    def toBinary(obj: AnyRef): Array[Byte] = {
        writeBinary(obj) // ???
    }

    def fromBinary(bytes: Array[Byte], clazz: Option[Class[_]]): AnyRef = {
        readBinary(bytes) // ???
    }
}

问题是我不能在没有相关的 Writer/Reader 的情况下调用 writeBinary/readBinary。有没有办法可以根据对象类查找这些?

4

2 回答 2

0

我找到了一种使用反射的方法。我的解决方案基于这样一个假设,即任何需要序列化的对象都应该在其伴随对象中定义了一个 ReadWriter:

class UpickleSerializer extends Serializer {

private var map = Map[Class[_], ReadWriter[AnyRef]]()

def includeManifest: Boolean = true
def identifier = 1234567

def toBinary(obj: AnyRef): Array[Byte] = {
    implicit val rw = getReadWriter(obj.getClass)
    writeBinary(obj)
}

def fromBinary(bytes: Array[Byte], clazz: Option[Class[_]]): AnyRef = {
    implicit val rw = lookup(clazz.get)
    readBinary[AnyRef](bytes)
}

private def getReadWriter(clazz: Class[_]) = map.get(clazz) match {
    case Some(rw) => rw
    case None =>
        val rw = lookup(clazz)
        map += clazz -> rw
        rw
}

private def lookup(clazz: Class[_]) = {
    import scala.reflect.runtime._
    val rootMirror = universe.runtimeMirror(clazz.getClassLoader)
    val classSymbol = rootMirror.classSymbol(clazz)
    val moduleSymbol = classSymbol.companion.asModule
    val moduleMirror = rootMirror.reflectModule(moduleSymbol)
    val instanceMirror = rootMirror.reflect(moduleMirror.instance)
    val members = instanceMirror.symbol.typeSignature.members
    members.find(_.typeSignature <:< typeOf[ReadWriter[_]]) match {
        case Some(rw) =>
            instanceMirror.reflectField(rw.asTerm).get.asInstanceOf[ReadWriter[AnyRef]]
        case None =>
            throw new RuntimeException("Not found")
    }
}

}

于 2020-09-05T18:35:26.013 回答
0

看看下面的文件,你应该会有一些想法!

CborAkkaSerializer.scala

LocationAkkaSerializer.scala

注意:这些序列化程序使用 cbor

于 2020-09-05T16:15:44.187 回答