使用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)
^
为了实现这一点,我可能缺少一些基本的隐含概念,而没有在编译时明确知道地图中每个字段的类型。
答案 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)