LoginSignup
3
3

More than 5 years have passed since last update.

Play Framework サーバーでJSONを拾ってリアクションする手短な書き方

Last updated at Posted at 2016-02-03

JSON投げの標的サーバーを作りたいです。でもパース面倒くさいです。

Play Framework Json case class あたりで検索すると参考になる記事がたくさん出てくるんですが、なんだかどれも今ひとつ簡単に思えないのです。いちいちAPIごとにクラス作るのはいいとして、どうせ1回くらいしか使わないのに毎回implicitを書くんですよね… お辛い… みたいな。

関連処理ごとどこかに隠蔽しようかなあとも思ったんですが(先送り体質)、それだと「どういうJSONを投げなきゃいけないのか」がコードから読み取れなくなりますので、逆に困ります。
とはいえ、リクエストの内容がおかしかったら場合分けしたいし、やりたいことはそれなりにあるので毎回書くのはやっぱり嫌。

というわけで関数を悪魔合体させて何とかします。Tryはおまけです。

ApiController.scala
trait ApiController extends Controller {

  def TryJsonAction[T](r: Reads[T])(act: T => Request[AnyContent] => Result): Action[AnyContent] = Action { request =>
    request.body.asJson.flatMap(_.asOpt[T](r)) match {
      case None => BadRequest
      case Some(apiValue) => Try { act(apiValue)(request) } match {
        case Success(result) => result
        case Failure(_) => InternalServerError
      }
    }
  }

  def TryAction[T](act: Request[AnyContent] => Result): Action[AnyContent] = Action { request =>
    Try (act(request)) match  {
      case Success(result) => result
      case Failure(_) => InternalServerError
    }
  }
  def TryAction[T](act: => Result): Action[AnyContent] = TryAction(_ => act)
}

使うときはこんな感じ。daoは適当、イメージです。

server.scala

class Server @Inject()(dao: WorkerDao) extends ApiController {

  case class CreateWorkerApiValue(name: String)
  def createWorker = TryJsonAction(Json.reads[CreateWorkerApiValue]) { apiValue => request =>
    Ok(dao.generate(apiValue.name).register.toJson)
  }

}

結構スッキリしましたね。多分動くんじゃないかなと思われます。

3
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
3