【问题标题】:Is it possible to write a upickle Serializer for akka是否可以为 akka 编写一个令人讨厌的序列化程序
【发布时间】:2020-12-24 13:38:06
【问题描述】:

我想使用 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。有没有办法根据对象类查找这些?

【问题讨论】:

    标签: scala akka upickle


    【解决方案1】:

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

    CborAkkaSerializer.scala

    LocationAkkaSerializer.scala

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

    【讨论】:

      【解决方案2】:

      我找到了一种使用反射的方法。我的解决方案基于这样一个假设,即任何需要序列化的对象都应该在其伴随对象中定义一个 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")
          }
      }
      

      }

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2010-09-22
        • 2012-09-02
        • 2015-01-07
        • 1970-01-01
        • 2011-03-18
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多