required: spray.httpx.marshalling.ToResponseMarshallable Error

纵饮孤独 提交于 2019-12-08 04:00:23

问题


Hey im pretty new to Spray and reactive mongo .

Im trying to return a list of result as json but i'm having some issue with converting the result to list of json.

this is my model

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

the Mongo method

 def getAll(): Future[List[Post]] ={
 val query = BSONDocument(
  "likes" -> BSONDocument(
    "$gt" -> 27))
   collection.find(query).cursor[Post].collect[List]()
}

and this is the route

val route1 =
  path("posts") {
    val res: Future[List[Post]]= mongoService.getAll()
    onComplete(res) {
      case Success(value) => complete(value)
      case Failure(ex)    => complete(ex.getMessage)
    }
  }    

error

type mismatch; found : List[com.example.model.Post] required: spray.httpx.marshalling.ToResponseMarshallable

thanks,

miki


回答1:


You'll need to define how a Post will be serialized, which you can do via a spray-json Protocol (see the docs for more detailed information). It's quite easy to do so, but before that, you'll also need to define a format for the BSONObjectId type, since there's no built-in support for that type in spray-json (alternatively, if object_id is a string representation of the BSONObjectId, think about removing the id property from your Post class or change it to be a String):

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

Now, we're able to define the actual protocol for the Post class:

object PostJsonProtocol extends DefaultJsonProtocol {
    implicit val format = jsonFormat5(Post.apply)
}

Furthermore, we'll also need to make sure that we have the defined format in scope:

import PostJsonProtocol._

Now, everything will compile as expected.

One more thing: have a look at the docs about the DSL structure of spray. Your mongoService.getAll() isn't within a complete block, which might not reflect your intentions. This ain't an issue yet, but probably will be if your route get more complex. To fix this issue simply put the future into the onComplete call or make it lazy:

val route1 =
  path("posts") {
    onComplete(mongoService.getAll()) {
      case Success(value) => complete(value)
      case Failure(ex)    => complete(ex.getMessage)
    }
  } 


来源:https://stackoverflow.com/questions/28130260/required-spray-httpx-marshalling-toresponsemarshallable-error

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!