Play2.4が対象。

参考リンク

JSON

動作確認用コード

  def index = Action.async(parse.json) { implicit rs =>
    rs.body.validate[RootDto].fold(
      valid = { root =>
        // rawでpostされたものをそのまま返却
        Future(Ok(Json.toJson(root)))
      },
      invalid = { e =>
        // 不備があったらエラーで返却
        Future(BadRequest(JsError.toJson(e)).as(JSON))
      }
    )
  }

Form

バリデーション

複数選択肢のいずれか (正規表現のORで表現)

"param" -> text.verifying(Constraints.pattern("(AAA|BBB|CCC)".r))

ピリオド区切りの複数パラメータの各値が全て選択肢に含まれるか

通常

"param" -> text.verifying(
    "パラメータエラー",
    value => value.get.split('.').forall(Array("AAA", "BBB", "CCC").contains)
)

Option型の場合

"param" -> optional(text).verifying(
    "パラメータエラー",
    value => value.isEmpty || value.get.split('.').forall(Array("AAA", "BBB", "CCC").contains)
)

デバッグ

ログ出力

log4jでログ出力します。

import org.slf4j.LoggerFactory
var logger = LoggerFactory.getLogger("application")

logger.debug("hoge")

テスト

@Injectができない

Can't find a constructor for classと表示される場合です。
Playを使っているならば以下で動作します。

import play.api.inject.guice.GuiceApplicationBuilder
import scala.reflect.ClassTag    

trait Inject {
  lazy val injector = (new GuiceApplicationBuilder).injector()
  def inject[T : ClassTag]: T = injector.instanceOf[T]
}

class XxxDaoImplSpec extends PlaySpecification {
    lazy val dao: XxxDao = Injection[XxxDao]

    // テストを記入 //
}

参考: scala – Specs2: how to test a class with more than one injected dependency? – Stack Overflow

testのときに設定ファイルを変更したい

build.sbtjavaOptions in Test += "-Dconfig.file=conf/application.test.conf"を追加する。
activator test -Dconfig.file=...では動作しない。

参考: java – play 2 how to override global settings while testing – Stack Overflow

その他

POST JSONをRFC3339準拠のDatetime変換

jodaTimeを暗黙的型変換するフォーマットを変換する。

implicit val rfc3339Read = Reads.jodaDateReads("yyyy-MM-dd'T'HH:mm:ssZ")
implicit val rfc3339Write = Writes.jodaDateWrites("yyyy-MM-dd'T'HH:mm:ssZ")

case class XxxDto(key: Option[String],
                  id: String,
                  name: JsValue,
                  begin_time: DateTime,
                  end_time: DateTime)
implicit val xxxReadsFormat = Json.reads[XxxDto]

参考: [Play 2.2.1 Scala] JSON Reading / Writing ISO8601 – Google グループ

ExecutionContextのエラーになる

Cannot find an implicit ExecutionContext. You might pass an (implicit ec: ExecutionContext) parameter to your method or import scala.concurrent.ExecutionContext.Implicits.global.

以下をimportすればOK。
本当はもっとちゃんと考える必要がある。

import play.api.libs.concurrent.Execution.Implicits.defaultContext