ReactiveMongo混合类型映射到BSONDocument

时间:2015-07-21 00:46:32

标签: scala reactivemongo

使用ReactiveMongo驱动程序我正在尝试序列化可能未知的键/字段的Map 混合类型Map[String, Any]到BSONDocument中。我的问题非常类似于here提到的,它引用了序列化地图here的ReactiveMongo文档示例。不幸的是,答案似乎只适用于一致类型的地图,而我需要任意。我的MapWriter如下:

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

以下编译和序列化很好,因为所有类型都是Ints

val allInts = Map("someInt" -> 1, "someOtherInt" -> 2)
val docFromMap: BSONDocument = BSON.writeDocument(allInts)    

然而,我似乎无法按摩它来处理Map[String,Any]

val mixedTypes = Map("someDouble" -> 234.324, "someString" -> "abc", "someInt" -> 1)
val docFromMap: BSONDocument = BSON.writeDocument(mixedTypes)

结果:

Error:(134, 54) could not find implicit value for parameter writer: reactivemongo.bson.BSONWriter[scala.collection.immutable.Map[String,Any],reactivemongo.bson.BSONDocument]
val docFromMap: BSONDocument = BSON.writeDocument(mixedTypes)
                                                 ^

为了实现这一点,我可能缺少一些基本的隐含概念,而没有在编译时明确知道地图中每个字段的类型。

1 个答案:

答案 0 :(得分:2)

根据cchantep的建议,我通过匹配地图中的不同类型并将它们写入文档,从而使事物更明确地类型安全。这当然可以扩展为处理嵌套的映射和数组。这里可以看到一个很好的例子:JsBSONHandler Gist。对于上面列出的混合类型的平面地图我的场景,这适用于我关心的值类型:

def writeObject(obj: Map[String,Any]): BSONDocument = BSONDocument(obj.map(writePair))

def writePair(p: (String, Any)): (String, BSONValue) = (p._1, p._2 match     {
    case value: String  => BSONString(value)
    case value: Double  => BSONDouble(value)
    case value: Int     => BSONInteger(value)
    case value: Boolean => BSONBoolean(value)
    case value: Long    => BSONLong(value)
    case other => BSONNull
})

用法:

val mixedTypes = Map("someDouble" -> 234.324, "someString" -> "abc", "someInt" -> 1)
val docFromMap: BSONDocument = writeObject(mixedTypes)