4
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Play Framework の Request Body をスマートにパースする

Posted at

はじめに

私は Action で Request Body の JSON からクラスにマッピングする、といった処理を良く書きます。
Action 内のコードでパースすることもできますが、 Play の機能を上手く使えば簡潔に書けるので、その方法をご紹介します。

問題のコード

素直に書くとこのような感じになります。

class MyController extends InjectedController {

  case class MyRequestBody(foo: String)

  implicit val myReads: Reads[MyRequestBody] = Json.reads[MyRequestBody]

  def myAction = Action { request =>
    request.body.asJson match {
      case None => UnsupportedMediaType
      case Some(json) => json.validate[MyRequestBody] match {
        case _: JsError => BadRequest
        case JsSuccess(body, _) =>
          // some process
          Ok
      }
    }
  }

}

Request Body が Json でなければ Unsupported Media Type 、Json を クラスにマッピングできなければ Bad Request を返す、というコードです。
一度だけならあまり問題にはなりませんが、毎回書くとなるとかなり煩わしいです。

改善後のコード

parse.json[A](implicit reader: Reads[A]) を使うことで、 Action の実行前にパースします。

class MyController extends InjectedController {

  case class MyRequestBody(foo: String)

  implicit val myReads: Reads[MyRequestBody] = Json.reads[MyRequestBody]

  def myAction: Action[MyRequestBody] = Action(parse.json[MyRequestBody])  { request =>
    val body: MyRequestBody = request.body
    // some process
    Ok
  }

}

かなり簡潔になったのではないでしょうか。
このコードでも前のコードと同様に Unsupported Media Type と Bad Request を返せます。

おわりに

Action の実行前に Request Body をパースする方法をご紹介しました。
仕様によって細かく分岐させなければいけない場合などもありますので、いつでも使えるわけではありませんが、多くのケースに適用できるのではないでしょうか。
是非使ってみてください。

4
2
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
4
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?