Play json Read and Default parameters for case cla

2019-04-13 05:20发布

I have a problem with default parameters and using Play Json Read. Here is my code:

  case class Test(action: String, storeResult: Option[Boolean] = Some(true), returndata: Option[Boolean] = Some(true))

  val json =
    """
      {"action": "Test"}"""

  implicit val testReads: Reads[Test] =
    (
      (JsPath \\ "action").read[String](minLength[String](1)) and
        (JsPath \\ "store_result").readNullable[Boolean] and
        (JsPath \\ "returndata").readNullable[Boolean]
      ) (Test.apply _)
  val js = Json.parse(json)

  js.validate[Test] match {
    case JsSuccess(a, _) => println(a)
    case JsError(errors) =>
      println("Here")
      println(errors)
  }

What I was hoping to get at the end is

Test("Test", Some(true), Some(true))

but I got:

Test("Test",None,None)

Why is this so? If I didn't provide parameter in the json why it didn't got default value? How to achieve what I want?

3条回答
够拽才男人
2楼-- · 2019-04-13 05:26

Do you really need Options in your case class if you supply default values? Without Options the following code should work

case class Test(action: String, storeResult: Boolean = true, returndata: Boolean = true)

  implicit val testReads: Reads[Test] =
    (
      (JsPath \\ "action").read[String](minLength[String](1)) and
        ((JsPath \\ "store_result").read[Boolean]  or Reads.pure(true)) and
        ((JsPath \\ "returndata").read[Boolean] or Reads.pure(true))
      ) (Test.apply _)

If you need Options then this code might work (not tested!)

case class Test(action: String, storeResult: Option[Boolean] = Some(true), returndata: Option[Boolean] = Some(true))


  implicit val testReads: Reads[Test] =
    (
      (JsPath \\ "action").read[String](minLength[String](1)) and
        ((JsPath \\ "store_result").read[Boolean]  or Reads.pure(true)).map(x=>Some(x)) and
        ((JsPath \\ "returndata").read[Boolean] or Reads.pure(true)).map(x=>Some(x))
      ) (Test.apply _)
查看更多
Anthone
3楼-- · 2019-04-13 05:31

in Play 2.6 you can write simply:

Json.using[Json.WithDefaultValues].reads[Test]
查看更多
我命由我不由天
4楼-- · 2019-04-13 05:32

It looks as if support for default parameters is in version 2.6.

A workaround for prior versions is to do something like the following:

object TestBuilder {
  def apply(action: String, storeResult: Option[Boolean], returndata: Option[Boolean]) =
    Test(
      action, 
      Option(storeResult.getOrElse(true)), 
      Option(returndata.getOrElse(true))
    )
}

implicit val testReads: Reads[Test] =
  (
    (JsPath \\ "action").read[String](minLength[String](1)) and
    (JsPath \\ "store_result").readNullable[Boolean] and
    (JsPath \\ "returndata").readNullable[Boolean]
  )(TestBuilder.apply _)
查看更多
登录 后发表回答