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
implicit def ValueMapWriter[V](implicit vw: BSONWriter[V, BSONValue]): BSONDocumentWriter[Map[String, V]] =
with
implicit def ValueMapWriter[V](implicit vw: BSONWriter[V, _ <: BSONValue]): BSONDocumentWriter[Map[String, V]] =
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.
来源:https://stackoverflow.com/questions/20387445/reactivemongo-serializing-a-map-into-a-bsondocument