I defined BSONDocumentWriter
s to map domain objects (case classes) to BSON documents to be persisted in MongoDB using the ReactiveMongo driver. Defining the writers is quite straight-forward for case classes (although tedious and error prone: I wish there was a Salat-like solution for that). However, I can't seem to be able to do the same for a Map[String,Any]
(where the values can be of type numeric, date or string). I found a code example that defines a generic writer (and reader) for a map:
implicit def MapWriter[V](implicit vw: BSONDocumentWriter[V]): BSONDocumentWriter[Map[String, V]] =
new BSONDocumentWriter[Map[String, V]] {
def write(map: Map[String, V]): BSONDocument = {
val elements = map.toStream.map { tuple =>
tuple._1 -> vw.write(tuple._2)
}
BSONDocument(elements)
}
}
but this does not work if there's no implicit BSONDocumentWriter
for the type V
, i.e., the snippet:
BSONDocument(
"_id" -> "asd",
"map" -> MapWriter[Any].write(Map("x" -> 1, "y" -> "2"))
)
does not compile:
could not find implicit value for parameter vw: reactivemongo.bson.BSONDocumentWriter[Any]
"map" -> MapWriter[Any].write(Map("x" -> 1, "y" -> "2"))
^
I thought maybe the writer should write to a BSONValue
instead of a BSONDocument
so I modified the example as follows:
implicit def ValueMapWriter[V](implicit vw: BSONWriter[V, BSONValue]): BSONDocumentWriter[Map[String, V]] =
new BSONDocumentWriter[Map[String, V]] {
def write(map: Map[String, V]): BSONDocument = {
val elements = map.toStream.map {
tuple =>
tuple._1 -> vw.write(tuple._2)
}
BSONDocument(elements)
}
}
And to keep things simple, I tried to use Int
as the value type but again, the snippet:
BSONDocument(
"_id" -> "asd",
"map" -> ValueMapWriter[Int].write(Map("x" -> 1, "y" -> 2))
)
does not compile:
could not find implicit value for parameter vw: reactivemongo.bson.BSONWriter[Int,reactivemongo.bson.BSONValue]
"map" -> ValueMapWriter[Int].write(Map("x" -> 1, "y" -> 2))
^
If the above had worked I could have used some base class as the value type and defined its implicit writer.
I am not sure why this is happening and how I can solve it. Maybe I am missing something obvious? Ideas?
The generic type parameter boundary for BSONValue in ValueMapWriter definition is not correct. If you change the line
with
then it should resolve the implicit writer for Int.
BTW simple-reactivemongo already does this. And I am also planning to add this functionality to ReactiveMongo Extensions.