我正在尝试编写一个通用的提取器,用于使用spray和spray-json解析json POST主体。
然而,我正在努力让它与多个模型一起工作。这是服务对象中的case语句:
import MyJsonProtocol._
...
def receive = {
case Post (Routes.person.post, p: Person) => sender ! Ok(Actions.person.post(p))
case Get (Routes.foo.forId(x)) => sender ! Ok(x)
case _ => sender ! Ok("No handler")
}
这是我写的提取器(只要在case语句的范围内只有一个JsonReader用于单个模型):
//NB. Json.parse returns an Option[T]
object Post extends Request {
def unapply[T:JsonReader](req: HttpRequest): Option[(String, T)] = req match {
case HttpRequest(POST, url, _, HttpBody(_, body), _) => Json.parse[T](body.asString).map((url, _))
case _ => None
}
}
但是,只要我添加一个新模型(和相关的JsonReader),代码就不再编译错误:
ambiguous implicit values:
[error] both value personFormat in object Json of type => spray.json.RootJsonFormat[com.rsslldnphy.foam.models.Person]
[error] and value animalFormat in object Json of type => spray.json.RootJsonFormat[com.rsslldnphy.foam.models.Animal]
[error] match expected type spray.json.JsonReader[T]
[error] case Post (Routes.person.post, p: Person) => sender ! Ok(Actions.person.post(p))
JsonReaders的泛型类型不同的事实似乎丢失了。这种类型的擦除?有没有办法解决这个问题?
到目前为止,这是项目的完整编译代码,其中ExampleService
中的注释解释了导致其中断的原因:github.com/rsslldnphy/foam。感谢您的帮助。
或者如果我想要的东西目前不可能,那么有人可以提出另一种方法吗?
答案 0 :(得分:2)
您需要为编译器提供明确的指令才能使其工作。正如您在下面看到的,编译器无法推断出T应该是什么。编译器需要能够动态地从请求中查看Json,并从中暗示一个类型(我们只能梦想它在做什么;)
def unapply[T:JsonReader](req: HttpRequest): Option[(String, T)] = (...) Json.parse[T] (...)
这意味着要完成这项工作,你必须明确注释帖子,如下所示:
import MyJsonProtocol._
...
def receive = {
case Post[Person] (Routes.person.post, p: Person) => sender ! Ok(Actions.person.post(p))
case Get (Routes.foo.forId(x)) => sender ! Ok(x)
case _ => sender ! Ok("No handler")
}
并将定义更改为此
case class Post[T: JsonReader] extends Request {
def unapply(req: HttpRequest): Option[(String, T)] = req match {
case HttpRequest(POST, url, _, HttpBody(_, body), _) => Json.parse[T](body.asString).map((url, _))
case _ => None
}
}