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(...)
}
Другие вопросы по тегам