使用 Map 作为字段的快速 json 反序列化

Fast json Deserialization with Map as field

我想将 Json 格式的 Array[Byte] 反序列化为下面描述的事件 class,我想尽快完成。事件 class 有几个 Int/String 字段,这应该不是问题。 json 格式的 Byte 数组的所有内容必须转换为 Map。 json/Map 的键未知,并且没有任何嵌套的 json 对象或数组。

例如 Json: {"someKey1": "someval", "someInt": 34, "anotherKey": 56} -> toMap

这是我到目前为止所做的

import play.api.libs.json.{JsObject, Json}

...

  override def line2Event(
                           line: Array[Byte],
                           id: Int
                         ): Event = {
    val map = Json.parse(line).as[JsObject].value.toMap
    val timestamp = map.getOrElse("timestamp", id).toString.toLong
    Event(id, "GenericJson", timestamp, map)


class Event(
             val id: Int,
             val eventType: String,
             val timestamp: Long,
             extraArgs: Map[String, Any]
           )

某些数据集的此播放 api 实现速度约为 25K messages/second。我想改进它。使用其他一些框架会有帮助吗?例如 jsoniter 之类的东西?

但是,在我的例子中,我没有带有特定字段的 class(即,json 的所有键值对都存储到事件的 Map 字段中).这个或另一个框架是否包含像我使用的那样但速度更快的解析方法?

所以,我也尝试过使用 jackson 解析

  lazy val module = new MapModule{}
  lazy val mapper = JsonMapper.builder()
  .addModule(module)
  .build()
  ...
  val map: Map[String, Any] = mapper.readValue(line, classOf[Map[String, Any]])

因为我需要一个不可变的 Scala 映射,请注意我还注册了 DefaultScalaModule。

不幸的是,由于这个 class 在 Flink 内部使用,它需要可序列化,而 DefaultScalaModule 不是(ObjectMapper 是)。其他库(如 jsoniter)也出现了类似的问题。该怎么办?我应该创建一个新问题吗?

编辑:我对 mapper 和 scalaModule 使用了惰性 vals(仅获得了 MapModule),现在它们在需要时被初始化(即在 flink worker 中)。 See "I have a NotSerializableException." part

速度约为80Kevents/second,比之前的实现至少快了3倍。也许直接将字节数组解析为 Map 也可以像播放一样快 json 但我找不到方法来做到这一点。