Is it possible to write a upickle Serializer for akka

137 views Asked by At

I would like to implement an akka Serializer using upickle but I'm not sure its possible. To do so I would need to implement a Serializer something like the following:

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

The problem is I cannot call writeBinary/readBinary without having the relevant Writer/Reader. Is there a way I can look these up based on the object class?

2

There are 2 answers

0
user79074 On BEST ANSWER

I found a way to do it using reflection. I base the solution on the assumption that any object that needs to be serialized should have defined a ReadWriter in its companion object:

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

}

0
Pritam Kadam On

Take a look at following files, you should get some ideas!

CborAkkaSerializer.scala

LocationAkkaSerializer.scala

Note: These serializers are using cbor