2

我有一个递归数据结构,我想为其编写一个自定义的 spray-json 序列化程序。

case class Counts(var count: Int, var properties: mutable.Map[String, Counts])

object MyJsonProtocol extends DefaultJsonProtocol {
  import DefaultJsonProtocol._

  implicit object CountsJsonFormat extends RootJsonFormat[Counts] {
    def read(json: JsValue) = ???
    def write(c: Counts) = {
      // Flatten count and properties into the same object.
      val properties = c.properties.toJson.asJsObject
      val fields = properties.fields + ("count" -> JsNumber(c.count))
      JsObject(fields.toSeq: _*)
    }
  }
}

如果您使用内置的序列化逻辑,我已经看过有关如何为案例类执行此操作的文档,但我不知道如何将其应用于自定义序列化程序。我得到这个编译器错误:

Cannot find JsonWriter or JsonFormat type class for scala.collection.mutable.Map[String,co.asku.acuity.EventCounter.Counts]
val properties = c.properties.toJson.asJsObject
                              ^
4

2 回答 2

1

默认情况下,spray-json 格式无法处理可变地图(请参阅邮件列表中不久前发生的讨论)。将类型更改为properties不可变 Map (我认为无论如何更好),您的格式将按预期工作。

于 2015-01-10T11:03:46.817 回答
0

要添加到edi的答案,使用toMap在我发布的示例中可以将可变映射转换为不可变映射。

然而,我实际上遇到了一个使用嵌套可变映射的更复杂的用例,所以我只是添加了一种格式来序列化它们,如下所示:

object JsonProtocol extends DefaultJsonProtocol {
  import DefaultJsonProtocol._

  implicit def mutableMapFormat[K :JsonFormat, V :JsonFormat] = new RootJsonFormat[mutable.Map[K, V]] {
    def read(value: JsValue) = ???
    def write(m: mutable.Map[K, V]) = m.toMap.toJson
  }

  implicit object CountsJsonFormat extends RootJsonFormat[Counts] {
    // ...
  }
}
于 2015-01-12T17:22:29.603 回答