【问题标题】:NotSerializableException for `Map[String, String]` alias`Map[String, String]` 别名的 NotSerializableException
【发布时间】:2013-07-16 14:36:22
【问题描述】:

我正在尝试将一个对象发送给一个远程参与者,但我遇到了这个异常:

ERROR akka.remote.EndpointWriter - Transient association error (association remains live)
java.io.NotSerializableException: scala.collection.immutable.MapLike$$anon$2

被序列化的对象是一个案例类:

case class LocationReport(idn: String, report: String, timestamp: Option[String], location: Attr, status: Attr, alarms: Attr, network: Attr, sensors: Attr) extends Message(idn) {

  val ts = timestamp getOrElse location("fix_timestamp")

  def json =
    (report ->
      ("TIME" -> ts) ~
      ("location" -> location) ~
      ("alarms" -> alarms) ~
      ("network" -> network) ~
      ("sensors" -> ((status ++ sensors) + ("CUSTOMCLOCK" -> Report.decodeTimestamp(ts)))))
}

Attr是一个类型重新定义:

type Attr = Map[String, String]

Message 类非常简单:

abstract class Message(idn: String) {
  def topic = idn
  def json(): JValue
}

我想知道类型别名/重新定义是否会混淆序列化程序。我想我正在使用 ProtoBuf 序列化,但我确实在堆栈跟踪中看到了 JavaSerializer

更多调试信息

我新建了一个 JavaSerializer 并单独序列化了每个 Map。只有一个 (alarms) 无法序列化。这是他们每个人的 toString:

这个失败了:

alarms = Map(LOWBATTERY -> 1373623446000)

这些成功了:

location = Map(a_value -> 6, latitude -> 37.63473, p_value -> 4, longitude -> -97.41459, fix_timestamp -> 3F0AE7FF, status -> OK, fix_type -> MSBL, CUSTOMCLOCK -> 1373644159000)
network = Map(SID -> 1271, RSSI -> 85)
sensors = Map(HUMIDITY -> -999, PRESSURE -> -999, LIGHT -> -999  9:52 AM)
status = Map(TEMPERATURE_F -> 923, CYCLE -> 4, TEMPERATURE1_C -> 335, CAP_REMAINING -> 560, VOLTAGE -> 3691, CAP_FULL -> 3897)

【问题讨论】:

  • 类型别名与此完全无关。这是一个运行时问题,类型别名仅存在于编译时。
  • 如果您没有为您的类定义 protobuf 协议并且正在使用这些协议,那么您没有使用 ProtobufSerialization。
  • @ViktorKlang 我把它改成了JavaSerialization,还是不行。我认为这与序列化Map 有关,正如@ghik 指出的那样,这不是由于别名。有什么想法吗?
  • 您如何创建要发送的地图?
  • 你正在扩展的 Message 类中有什么?

标签: scala exception serialization akka


【解决方案1】:

问题是Map.mapValues 产生了一个不可序列化的对象。创建警报时,它会通过alarms.mapValues(hex2Int) 之类的东西运行。此处描述了问题和解决方法:

https://issues.scala-lang.org/browse/SI-7005

简而言之,解决办法就是做alarms.mapValues(hex2Int).map(identity)

【讨论】:

    【解决方案2】:

    不确定这是否适用于所有情况,但我的解决方法是在序列化之前将地图转换为序列(只是序列之前的.toSeq)。 toMap 应该在反序列化后给你同样的地图。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-03-17
      • 1970-01-01
      • 1970-01-01
      • 2013-12-18
      • 1970-01-01
      • 2020-08-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多