4

我需要将akka事件序列化为json。基于“在 Scala 中使用什么 JSON 库? ”我尝试了几个库。由于我的序列化程序对我的所有具体事件一无所知,因此由案例类和案例对象组成的事件应该使用反射进行序列化。json4s似乎最符合我的要求。

class Json4sEventAdapter(system: ExtendedActorSystem) extends EventAdapter {
  implicit val formats = Serialization.formats(FullTypeHints(List(classOf[Evt])))
  override def toJournal(event: Any): Any = event match {
case e: AnyRef =>
  write(e).getBytes(Charsets.UTF_8)}

override def fromJournal(event: Any, manifest: String): EventSeq = event match {
case e: Array[Byte] => {
      EventSeq.single(read[Evt](new String(e.map(_.toChar))))}}

使用 json4s 的问题是,无论使用哪种实现,对象的反序列化都会产生不同的实例。由于我们对 case 对象大量使用模式匹配,这会破坏我们现有的所有代码。

所以我的问题是:在存储案例对象时,哪个 JSON 库可以与 scala 和 akka 持久性一起使用?

是否有一个库可以正确地通过反射处理案例对象的反序列化?- 或者有没有人有一个好的解决方法?

4

2 回答 2

0

我强烈建议你看看Stamina。它已被实施以解决您在使用 akka-persistence 时遇到的大多数常见问题。

它提供了一个支持版本控制、读取时自动迁移的 json 序列化器(基于 spray-json 和 shapeless)以及一个测试工具包,以确保所有旧版本的持久事件仍然可读。

于 2016-08-02T12:37:51.117 回答
0

我无法评论 Json4s,因为我从未使用过它,但我知道这在play-json中不是问题。你会做这样的事情:

import play.api.libs.json._

sealed trait MyEventBase
case object MyEvent extends MyEventBase

implicit val myEventBaseFormat: Format[MyEventBase] = Format(Reads.StringReads.collect(ValidationError("must be the string `MyEvent`") {
  case "MyEvent" => MyEvent
}, Writes.pure("MyEvent"))

在这种情况下,序列化是一个裸字符串,所以我搭载内置StringReads断言该项目应该可以反序列化为一个字符串,然后使用它collect来缩小到特定的字符串。但基本思想是您提供您想要从Reads实例中的反序列化中返回的特定值。在这里,它是单例case object。因此,每当您反序列化 aMyEventBase结果为 aMyEvent时,您肯定会得到相同的实例。

在现实世界中,MyEventBase可能还有其他子类型,因此您构建您的Writes实例以创建某种形式的类型标签用于序列化,您的Reads实例可以关闭该标签以反序列化为正确的子类型。例如,您可能会序列化为 JSON 对象而不是裸字符串,并且该对象将具有type标识子类型的字段。或者只是使用Play JSON Extensions 之类的东西来自动Format为您的sealed trait.

于 2015-11-02T06:03:51.010 回答