自定义akka持久性(Play!)JSON(de)序列化程序

时间:2015-01-27 14:41:44

标签: json scala serialization persistence akka

我有相关演员的消息(de)可以序列化为Play游戏! JSON。我想为akka persistance系统使用JSON(de)序列化器(如果可能的话)。

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

谢谢!

最佳!

2 个答案:

答案 0 :(得分:0)

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

答案 1 :(得分:0)

将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序列化程序应能够将其序列化(反序列化)到构造函数的所有类型传递播放格式。必须在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)
}