scala spray-json中的递归数据类型和自定义序列化程序

chy5wohz  于 2023-02-19  发布在  Scala
关注(0)|答案(3)|浏览(168)

我有一个递归数据结构,我想为它编写一个定制的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: _*)
    }
  }
}

我已经看过文档,如果你使用内置的序列化逻辑,如何为case类做这件事,但我不知道如何将其应用到自定义序列化器。

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

hec6srdp1#

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

68bkxrlz

68bkxrlz2#

补充一下edi的答案,在我发布的例子中,使用toMap将可变Map转换为不可变Map。
然而,我实际上遇到了一个使用嵌套可变Map的更复杂的用例,所以我只是添加了一个格式来序列化它们,如下所示:

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] {
    // ...
  }
}
kupeojn6

kupeojn63#

这段代码为可变Map提供了序列化和反序列化支持(并且可以为其他可变集合进行简单的修改):

import spray.json._
import spray.json.DefaultJsonProtocol._
import scala.collection.mutable
...
implicit def mutableMapFormat[K : JsonFormat, V : JsonFormat] = new RootJsonFormat[mutable.Map[K, V]] {
    def write(m : mutable.Map[K, V]) = mapFormat[K, V].write(m.toMap)
    def read(value : JsValue) = mutable.Map.empty[K, V] ++ mapFormat[K, V].read(value)
}

相关问题