要求:spray.httpx.marshalling.ToResponseMarshallable 错误
required: spray.httpx.marshalling.ToResponseMarshallable Error
嘿,我对 Spray 和反应式还很陌生 mongo。
我正在尝试 return 作为 json 的结果列表,但我在将结果转换为 json 列表时遇到了一些问题。
这是我的模型
import reactivemongo.bson.BSONDocumentReader
import reactivemongo.bson.BSONObjectID
import reactivemongo.bson.Macros
case class Post(id: BSONObjectID, likes: Long, message: String, object_id: String, shares: Long)
object Post {
implicit val reader: BSONDocumentReader[Post] = Macros.reader[Post]
}
Mongo方法
def getAll(): Future[List[Post]] ={
val query = BSONDocument(
"likes" -> BSONDocument(
"$gt" -> 27))
collection.find(query).cursor[Post].collect[List]()
}
这是路线
val route1 =
path("posts") {
val res: Future[List[Post]]= mongoService.getAll()
onComplete(res) {
case Success(value) => complete(value)
case Failure(ex) => complete(ex.getMessage)
}
}
错误
type mismatch; found : List[com.example.model.Post] required: spray.httpx.marshalling.ToResponseMarshallable
谢谢,
三木
您需要定义 Post
将如何序列化,这可以通过 spray-json 协议来实现(请参阅 docs 了解更多详细信息)。这样做很容易,但在此之前,您还需要为 BSONObjectId
类型定义一种格式,因为在 spray-json 中没有对该类型的内置支持(或者,如果 object_id
是 BSONObjectId
的字符串表示形式,请考虑从 Post
class 中删除 id
属性 或将其更改为字符串):
// necessary imports
import spray.json._
import spray.httpx.SprayJsonSupport._
implicit object BSONObjectIdProtocol extends RootJsonFormat[BSONObjectID] {
override def write(obj: BSONObjectID): JsValue = JsString(obj.stringify)
override def read(json: JsValue): BSONObjectID = json match {
case JsString(id) => BSONObjectID.parse(id) match {
case Success(validId) => validId
case _ => deserializationError("Invalid BSON Object Id")
}
case _ => deserializationError("BSON Object Id expected")
}
}
现在,我们可以为 Post
class:
定义实际的协议
object PostJsonProtocol extends DefaultJsonProtocol {
implicit val format = jsonFormat5(Post.apply)
}
此外,我们还需要确保在范围内定义了格式:
import PostJsonProtocol._
现在,一切都将按预期编译。
还有一件事:看看喷的docs about the DSL structure。您的 mongoService.getAll()
不在 complete
块内,这可能无法反映您的意图。这还不是问题,但如果您的路线变得更复杂,则可能会成为问题。要解决此问题,只需将 future 放入 onComplete
调用中或使其变得懒惰:
val route1 =
path("posts") {
onComplete(mongoService.getAll()) {
case Success(value) => complete(value)
case Failure(ex) => complete(ex.getMessage)
}
}
嘿,我对 Spray 和反应式还很陌生 mongo。
我正在尝试 return 作为 json 的结果列表,但我在将结果转换为 json 列表时遇到了一些问题。
这是我的模型
import reactivemongo.bson.BSONDocumentReader
import reactivemongo.bson.BSONObjectID
import reactivemongo.bson.Macros
case class Post(id: BSONObjectID, likes: Long, message: String, object_id: String, shares: Long)
object Post {
implicit val reader: BSONDocumentReader[Post] = Macros.reader[Post]
}
Mongo方法
def getAll(): Future[List[Post]] ={
val query = BSONDocument(
"likes" -> BSONDocument(
"$gt" -> 27))
collection.find(query).cursor[Post].collect[List]()
}
这是路线
val route1 =
path("posts") {
val res: Future[List[Post]]= mongoService.getAll()
onComplete(res) {
case Success(value) => complete(value)
case Failure(ex) => complete(ex.getMessage)
}
}
错误
type mismatch; found : List[com.example.model.Post] required: spray.httpx.marshalling.ToResponseMarshallable
谢谢,
三木
您需要定义 Post
将如何序列化,这可以通过 spray-json 协议来实现(请参阅 docs 了解更多详细信息)。这样做很容易,但在此之前,您还需要为 BSONObjectId
类型定义一种格式,因为在 spray-json 中没有对该类型的内置支持(或者,如果 object_id
是 BSONObjectId
的字符串表示形式,请考虑从 Post
class 中删除 id
属性 或将其更改为字符串):
// necessary imports
import spray.json._
import spray.httpx.SprayJsonSupport._
implicit object BSONObjectIdProtocol extends RootJsonFormat[BSONObjectID] {
override def write(obj: BSONObjectID): JsValue = JsString(obj.stringify)
override def read(json: JsValue): BSONObjectID = json match {
case JsString(id) => BSONObjectID.parse(id) match {
case Success(validId) => validId
case _ => deserializationError("Invalid BSON Object Id")
}
case _ => deserializationError("BSON Object Id expected")
}
}
现在,我们可以为 Post
class:
object PostJsonProtocol extends DefaultJsonProtocol {
implicit val format = jsonFormat5(Post.apply)
}
此外,我们还需要确保在范围内定义了格式:
import PostJsonProtocol._
现在,一切都将按预期编译。
还有一件事:看看喷的docs about the DSL structure。您的 mongoService.getAll()
不在 complete
块内,这可能无法反映您的意图。这还不是问题,但如果您的路线变得更复杂,则可能会成为问题。要解决此问题,只需将 future 放入 onComplete
调用中或使其变得懒惰:
val route1 =
path("posts") {
onComplete(mongoService.getAll()) {
case Success(value) => complete(value)
case Failure(ex) => complete(ex.getMessage)
}
}