Play Action Composition - параметризованный парсер жесткого кодирования
Я хотел бы создать пользовательское действие, которое устраняет шаблон написания таких действий:
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]
он говорит мне, что нет сериализатора Json для типа А.
Есть ли другой способ определить это пользовательское действие?
2 ответа
ActionBuilder
недостаточно универсален для вашего варианта использования; вам некуда пройти в вашем Reads[T]
,
Там нет ничего особенного ActionBuilder
хоть. Это коллекция apply
а также async
заводские методы. Вы можете определить свой собственный тип Action с любыми фабричными методами, которые вам нужны:
object 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 => ??? }
Да, я пытался заставить это работать с официальным ActionBuilder
образ жизни и просто не может заставить типы выстраиваться в линию.
Вот кое-что, что работает для меня, хотя:
object JsonActionHelper {
def withReads[A](act: Request[A] => Future[Result])(implicit reads:Reads[A]) =
Action.async(BodyParsers.parse.json(reads))(act)
}
Использование в вашем контроллере (FooJson
является object
содержащий неявный Reads[Foo]
):
import models.FooJson._
import JsonActionHelper._
def handleIncomingFoo(fooId:String) = withReads[Foo] { req =>
val foo:Foo = req.body
...
Ok(...)
}