2015-01-08 33 views
2

我有一個遞歸數據結構,我想要編寫一個自定義噴霧json序列化程序。噴霧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 
          ^

回答

1

噴霧JSON格式無法在默認情況下處理可變地圖(見this disussion已經發生前一陣子在郵件列表)。將properties的類型更改爲不可變的Map(我認爲它更好),並且您的格式將按預期工作。

+0

感謝;我出於各種原因使用可變映射,並沒有意識到spray-json默認不支持它們。有沒有理由不這樣做? – tmandry

+0

不,對不起。但是,如果你想了解哪些集合被支持,哪些不是你可以看看[CollectionFormats](https://github.com/spray/spray-json/blob/master/src/main/scala /spray/json/CollectionFormats.scala)。 – edi

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