问题
Here below is a case class that represents an user, and its companion object provides a BSONDocumentWriter
and BSONDocumentReader
to serialize/deserialize to/from BSON:
case class User(
id: Option[BSONObjectID],
name: String,
addresses: Option[List[BSONObjectID]]
)
object User {
implicit object UserWriter extends BSONDocumentWriter[User] {
def write(user: User) = BSONDocument(
"_id" -> user.id.getOrElse(BSONObjectID.generate),
"name" -> user.name,
"addresses" -> user.addresses
)
}
implicit object UserReader extends BSONDocumentReader[User] {
def read(doc: BSONDocument) = User(
doc.getAs[BSONObjectID]("_id"),
doc.getAs[String]("name").get,
doc.getAs[List[BSONObjectID]]("addresses").toList.flatten,
)
}
}
The code above does not compile because User.addresses
is an Option
and I always get the following error:
/home/j3d/Projects/test/app/models/User.scala:82: polymorphic expression cannot be instantiated to expected type;
[error] found : [B]List[B]
[error] required: Option[List[reactivemongo.bson.BSONObjectID]]
[error] doc.getAs[List[BSONObjectID]]("addresses").toList.flatten,
^
If the input BSON contains addresses
, how do I deserialize it into an Option[List[BSONObjectID]]
?
回答1:
Why are you calling toList
and then flatten
? If I'm reading the docs correctly for BSONDocument
, the getAs
method will return an Option
for type T
where in your case, you are specifying T
as List[BSONObjectID]
. When you call toList
, you are basically unpacking the Option
to either an empty List
(in the case of a None
) or into the actual List
in the case of a Some
. And then the flatten
here doesn't seem to be doing anything relevant. Can't you just do it as:
doc.getAs[List[BSONObjectID]]("addresses")
来源:https://stackoverflow.com/questions/20871159/reactivemongo-how-to-deserialize-a-list-into-an-option