Reputation: 1375
I have a recursive data structure that I want to write a custom spray-json serializer for.
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: _*)
}
}
}
I've seen the documentation for how to do this for a case class if you use the builtin serialization logic, but I have no idea how to apply that to a custom serializer. I get this compiler error:
Cannot find JsonWriter or JsonFormat type class for scala.collection.mutable.Map[String,co.asku.acuity.EventCounter.Counts]
val properties = c.properties.toJson.asJsObject
^
Upvotes: 2
Views: 1001
Reputation: 2490
This code provides serialization and deserialization support for mutable maps (and can be modified trivially for other mutable collections):
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)
}
Upvotes: 0
Reputation: 1375
To add to edi's answer, using toMap
would have worked in the example I posted, to convert the mutable map to immutable.
However, I actually ran into a more complex usecase using nested mutable maps, so I just added a format to serialize them like this:
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] {
// ...
}
}
Upvotes: 0
Reputation: 3122
spray-json formats can't handle mutable Maps by default (see this disussion that has happened a while ago on the mailing list). Change the type of properties
to be an immutable Map (which I think is better anyways) and your format will work as expected.
Upvotes: 1