2013-12-04 5 views
2

Я определил BSONDocumentWriter s для сопоставления объектов домена (классов case) с документами BSON, которые должны сохраняться в MongoDB с использованием драйвера ReactiveMongo. Определение авторов довольно прямолинейно для классов case (хотя утомительно и подвержено ошибкам: я бы хотел, чтобы для этого было решение, подобное Salat). Однако я не могу сделать то же самое для Map[String,Any] (где значения могут иметь тип numeric, date или string). Я нашел code example, который определяет общий писатель (и читателя) на карте:Reactivemongo сериализация карты в BSONDocument

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) 
    } 
} 

, но это не работает, если нет никаких неявных BSONDocumentWriter для типа V, т.е. сниппета:

BSONDocument(
    "_id" -> "asd", 
    "map" -> MapWriter[Any].write(Map("x" -> 1, "y" -> "2")) 
) 

не компилируется:

could not find implicit value for parameter vw: reactivemongo.bson.BSONDocumentWriter[Any] 
    "map" -> MapWriter[Any].write(Map("x" -> 1, "y" -> "2")) 
        ^

Я подумал, что писатель должен писать в BSONValue вместо BSONDocument поэтому я изменил пример следующим образом:

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) 
    } 
} 

И держать вещи простыми, я пытался использовать Int как тип значения, но опять же, фрагмент кода:

BSONDocument(
    "_id" -> "asd", 
    "map" -> ValueMapWriter[Int].write(Map("x" -> 1, "y" -> 2)) 
) 

не компилируется:

could not find implicit value for parameter vw: reactivemongo.bson.BSONWriter[Int,reactivemongo.bson.BSONValue] 
    "map" -> ValueMapWriter[Int].write(Map("x" -> 1, "y" -> 2)) 
         ^

Если это было выполнено, я мог бы использовать некоторый базовый класс в качестве типа значения и определить его неявный писатель.

Я не уверен, почему это происходит и как я могу это решить. Может быть, мне не хватает чего-то очевидного? Идеи?

ответ

1

Граница общего типа параметра для BSONValue в ValueMapWriter определение не является правильным. Если вы измените строку

implicit def ValueMapWriter[V](implicit vw: BSONWriter[V, BSONValue]): BSONDocumentWriter[Map[String, V]] = 

с

implicit def ValueMapWriter[V](implicit vw: BSONWriter[V, _ <: BSONValue]): BSONDocumentWriter[Map[String, V]] = 

, то он должен решить неявный писатель для Int.

BTW simple-reactivemongo уже делает это. И я также планирую добавить эту функциональность в ReactiveMongo Extensions.

+0

Не проверял его, потому что, к сожалению, я больше не работаю с Scala, но это имеет смысл. –

Смежные вопросы