播放动作合成 - 硬编码参数化解析器

时间:2016-04-18 00:21:07

标签: scala playframework play-json context-bound

我想创建一个自定义操作,它会删除写这样的动作的样板:

Action[MyClass](BodyParsers.parse.json[MyClass]) { req => ...

但是,我一直在遇到类定义错误。这是我最成功的尝试:

class JsonAction[A: Reads] extends ActionBuilder[Request] {
  def hardcodedJson[A: Reads](action: Action[A]) = 
    Action.async(BodyParsers.parse.json[A]) { request => action(request) }

  def invokeBlock[A: Reads](request: Request[A], block: (Request[A]) => Future[Result]) = {
    block(request)
  }
  override def composeAction[A: Reads](action: Action[A]) = hardcodedJson(action)
}

但是我收到以下错误:method composeAction overrides nothing.

如果我将composeAction[A: Reads]更改为composeAction[A],它会告诉我没有类型A的Json序列化程序。

还有其他方法可以定义此自定义操作吗?

2 个答案:

答案 0 :(得分:1)

是的,我试图让这个与官方的ActionBuilder方式一起工作,但是无法让这些类型排成一行。

这里有一些对我有用的东西:

object JsonActionHelper {
  def withReads[A](act: Request[A] => Future[Result])(implicit reads:Reads[A]) = 
    Action.async(BodyParsers.parse.json(reads))(act)
}

控制器中的用法(FooJsonobject,其中包含隐式Reads[Foo]):

import models.FooJson._
import JsonActionHelper._

def handleIncomingFoo(fooId:String) = withReads[Foo] { req =>
  val foo:Foo = req.body
  ...
  Ok(...)
}

答案 1 :(得分:1)

Reads[T]对于您的用例来说不够通用;你无处可去传递ActionBuilder

虽然apply没有什么特别之处。它是asyncobject JsonAction { def apply[A : Reads](request: Request[A] => Result) = Action(BodyParsers.parse.json[A])(request) } // these are equivalent: Action[MyClass](BodyParsers.parse.json[MyClass]) { req => ??? } JsonAction[MyClass] { req => ??? } 工厂方法的集合。您可以使用您需要的任何工厂方法定义自己的Action类型:

 $query = 'SELECT *
      FROM student 
      WHERE GPA >= :GPA
      ORDER BY studentID';
 $statement->bindValue(':GPA', $GPA, PDO::PARAM_STR);