升级Play与ReactiveMongo依赖后出现类型不匹配错误求助
解决ReactiveMongo升级后BSONDocument类型不匹配问题
你遇到的错误核心是类型不匹配:升级后的ReactiveMongo版本对类型检查更严格了,BSONDocument的元素要求是(String, BSONValue)类型,但你传入的Json.toJson(ZonedDateTime.now())返回的是JsValue,两者无法直接兼容——之前的版本可能有宽松的隐式转换,但新版本已经调整了这个逻辑。
先回顾你碰到的具体错误:
found : (String, play.api.libs.json.JsValue) [error] required: reactivemongo.bson.Producer[reactivemongo.bson.BSONElement] [error] (which expands to) reactivemongo.bson.Producer[(String, reactivemongo.bson.BSONValue)] [error] Error occurred in an application involving default arguments. [error] claimsCollection.update(BSONDocument("id" -> claimId), BSONDocument("$set" -> BSONDocument("status"-> "Approved" , "updationDate" -> Json.toJson(ZonedDateTime.now()))))
结合你使用JSONCollection的代码场景,这里有两个简洁的解决方案:
方案一:改用Play JSON的JsObject构建更新语句
JSONCollection本身就是为了和Play的JSON API无缝协作设计的,直接用JsObject替代BSONDocument,就能自动利用ReactiveMongo提供的JSON-BSON隐式转换,完全避免手动类型转换的麻烦:
修改你的approveClaim方法:
def approveClaim(claimId:String)(implicit ec :ExecutionContext): Future[WriteResult] = { claimsCollection.update( Json.obj("id" -> claimId), Json.obj("$set" -> Json.obj( "status"-> "Approved", "updationDate" -> Json.toJson(ZonedDateTime.now()) )) ) }
注意:Play默认不支持ZonedDateTime的JSON序列化,你需要先定义对应的格式器,可以添加在代码的合适位置:
import play.api.libs.json._ import java.time.ZonedDateTime import java.time.format.DateTimeFormatter // 定义ZonedDateTime的JSON读写规则 implicit val zonedDateTimeFormat: Format[ZonedDateTime] = Format( Reads[ZonedDateTime](js => js.validate[String].map(str => ZonedDateTime.parse(str, DateTimeFormatter.ISO_ZONED_DATE_TIME)) ), Writes[ZonedDateTime](dt => JsString(dt.format(DateTimeFormatter.ISO_ZONED_DATE_TIME)) ) )
方案二:手动将JsValue转换为BSONValue
如果你坚持要使用BSONDocument,可以利用你已经导入的ImplicitBSONHandlers._隐式转换,把JsValue转成BSONValue:
修改后的方法:
def approveClaim(claimId:String)(implicit ec :ExecutionContext): Future[WriteResult] = { // 借助隐式转换自动将JsValue转为BSONValue val updationDateBson: BSONValue = Json.toJson(ZonedDateTime.now()) claimsCollection.update( BSONDocument("id" -> claimId), BSONDocument("$set" -> BSONDocument( "status"-> "Approved", "updationDate" -> updationDateBson )) ) }
同样,这个方案也需要你先定义好ZonedDateTime的JSON格式器,否则Json.toJson(ZonedDateTime.now())会报错。
个人更推荐方案一,因为它更符合JSONCollection的设计初衷,代码更简洁,也能减少后续维护时的类型问题。
内容的提问来源于stack exchange,提问作者Manoj S Ramaswamy
相关产品推荐
相关产品推荐

