【问题标题】:Custom akka persistence (Play!) JSON (de)serializer自定义 akka 持久性 (Play!) JSON (de)serializer
【发布时间】:2015-03-26 05:20:48
【问题描述】:

我有我的相关演员的消息(反)可序列化到 Play! JSON。我想将 JSON (de)serializers 用于 akka 持久性系统(如果可能的话)。

akka persistance 文档中可以使用我们自己的序列化程序。更多here 是如何编写自定义序列化程序的说明。由于akka.serialization.Serializer 期待toBinaryfromBinary,有没有办法使用具有akka 持久性的Play JSON 序列化程序?

谢谢!

最好的!

【问题讨论】:

  • JSON 到底是什么?你能把它序列化成String吗?你能把String序列化成Array[Byte]吗?
  • 你有没有找到一个简单的方法来做到这一点?

标签: json scala serialization persistence akka


【解决方案1】:

您希望将数据序列化到哪里? 我正在寻找一个基于 mongodb 的 akka 持久性存储,其中包含我自己使用 json 格式的序列化对象。也许以下驱动程序对您也很有趣: https://github.com/scullxbones/akka-persistence-mongo/issues/16

【讨论】:

    【解决方案2】:

    将 play json 集成到 akka-persistence 中很复杂,因为 play json 使用通过隐式收集的 Format 实例。 Akka 仅提供 java.lang.Object 用于序列化和 java.lang.Class[_] 用于反序列化,这使得解析正确的隐式 Format 成为不可能。

    您可以做的是编写一个自定义的akka.serialization.Serializer,它的MapClass[A]Format[A]。此映射可用于查找java.lang.Object / java.lang.Class[_] 的正确格式:

    class JsonSerializer(serializers: Map[Class[_], Format[_]]) extends Serializer {
      val charset: Charset = StandardCharsets.UTF_8
      val identifier: Int = "play-json-serializer".##
      val includeManifest: Boolean = true
    
      def serializer[A](c: Class[_]): GenericFormat[A] = serializers.get(c) match {
        case Some(format) => format.asInstanceOf[GenericFormat[A]]
        case None => throw new RuntimeException("No Format available for " + c.getName)
      }
    
      def toBinary(o: AnyRef): Array[Byte] = jsonSerialize(o).getBytes(charset)
      def fromBinary(bytes: Array[Byte], manifest: Option[Class[_]]): AnyRef = jsonDeserialize(bytes, manifest.get)
    
      def jsonSerialize[A](a: A): String = {
        implicit val format: GenericFormat[A] = serializer[A](a.getClass)
        Json.stringify(Json.toJson(a))
      }
    
      def jsonDeserialize[A](bytes: Array[Byte], manifest: Class[_]): A = {
        implicit val format: GenericFormat[A] = serializer[A](manifest)
        Json.fromJson[A](Json.parse(new String(bytes, charset))).get
      }
    }
    

    您现在可以继承这个类并将您的 akka-serializer 应该能够(反)序列化的所有类型的播放格式传递给构造函数。这个序列化器必须在akka配置as described in the documentation中配置:

    class MyJsonSerializer extends JsonSerializer(Map(
      Serializer[Foo], Serializer[...], ...
    ))
    
    // Just a utility class for the pretty syntax above
    object Serializer {
      def apply[A](implicit format: Format[A], ctag: ClassTag[A]): (Class[A], Format[A]) =
        (ctag.runtimeClass.asInstanceOf[Class[A]], format)
    }
    

    【讨论】:

      猜你喜欢
      • 2015-02-15
      • 2014-10-19
      • 2019-02-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多