我有一块代码块可以在整个地方进行复制。这段代码(大约10行)处理入站操作,验证它们,处理JSON序列化,并调用内部函数,准备结果。
我知道可以将其减少为对普通辅助函数的单行调用,但由于隐含,类型以及我对Scala语法的了解不多,我一直遇到问题。
代码(两个单独的示例,用于演示它们的不同之处):
val authenticate = GPAuthenticatedAction(parse.json) { implicit request =>
request.body.validate[AuthenticationRequest] match {
case JsSuccess(request, _) => {
val (status, response) = performAuthentication(request)
status(Json.toJson(response.asInstanceOf[AuthenticationResponse]))
}
case e: JsError => NotAcceptable(Json.toJson(GPError.MalformedJSON.value(e.toString + " REQUEST: " + request.body.toString)))
}
}
val register = GPAuthenticatedAction(parse.json) { implicit request =>
request.body.validate[RegistrationRequest] match {
case JsSuccess(request, _) => {
val (status, response) = performRegistration(request)
status(Json.toJson(response.asInstanceOf[RegistrationResponse]))
}
case e: JsError => NotAcceptable(Json.toJson(GPError.MalformedJSON.value(e.toString + " REQUEST: " + request.body.toString)))
}
}
正如您所见 - 非常非常相似,但请求类型(AuthenticationRequest
与RegistrationRequest
)和响应类型(AuthenticationResponse
与{{1}除外})。否则它是样板。
应该有办法将其提炼为类似的东西:
RegistrationResponse
我在定义val register = GPAuthenticatedAction(parse.son) from(RegistrationRequest, RegistrationResponse)
时花了很多钱,但这导致了一系列问题(没有关于JSON反序列化的信息等)。所以,我尝试通过创建一些特征from[I,O](request: I, response: O)
和GPRequest
来抽象出来:
GPResult
然后尝试定义一个函数,如:
trait GPRequest[T] {
implicit val format = Json.format[T]
}
trait GPResponse[T] {
implicit val format: Format[T] = Json.format[T]
def from(error: GPError): GPResponse
}
但这会导致各种形式的问题。我在下面粘贴了编译器错误,但一般的要点是:
def from[I: GPRequest, O: GPResponse](request: Request) { implicit request =>
request.body.validate[I] match {
case JsSuccess(request, _) => {
val (status, response) = performAuthentication(request)
status(Json.toJson(response.asInstanceOf[O]))
}
case e: JsError => NotAcceptable(Json.toJson(GPError.MalformedJSON.value(e.toString + " REQUEST: " + request.body.toString)))
}
}
和apply
。unapply
(我的Scala语法可能已经搞砸了)。情况变得更糟。
底线问题:有没有人有一个干净的设计模式来实现我在这里寻找的东西?(或者,知道Play和Scala的人可以提供一些指导从这里开始)。这看起来应该是可能的,但我很难搞清楚下一步。
对于勇敢者,以下是错误:
implicit
答案 0 :(得分:1)
您可以编写父案例类而不是特征,并扩展现有类型:
AuthenticationRequest, RegistrationRequest, AuthenticationResponse, RegistrationResponse
是新的父案例类的子类。
有了这个,您可以更改签名以扩展您的泛型类型:
def from[I <: GPRequest, O <: GPResponse]