将play json集成到akka-persistence中是比较复杂的,因为play json使用通过隐式参数收集的Format
实例。Akka仅提供java.lang.Object
用于序列化和java.lang.Class [_]
用于反序列化,这使得解析正确的隐式Format
变得不可能。
您可以编写自定义的akka.serialization.Serializer
,其中包含从Class[A]
到Format[A]
的Map
。该映射可用于查找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 配置中配置此序列化器 如文档所述:
class MyJsonSerializer extends JsonSerializer(Map(
Serializer[Foo], Serializer[...], ...
))
object Serializer {
def apply[A](implicit format: Format[A], ctag: ClassTag[A]): (Class[A], Format[A]) =
(ctag.runtimeClass.asInstanceOf[Class[A]], format)
}
String
吗?你能将String
序列化为Array[Byte]
吗? - Cem Catikkas