-->

unable to understand why validateOpt will return `

2019-08-17 12:31发布

问题:

In the following code, I am unable to understand why validateOpt might return value JsSuccess(None) instead of JsError

def getQuestion = silhouette.UserAwareAction.async{ 

    implicit request => {        
      val body: AnyContent = request.body
      val jsonBodyOption: Option[JsValue] = body.asJson

      jsonBodyOption.map((jsonBody:JsValue) => { //body is json
        val personJsonJsResultOption = jsonBody.validateOpt[Person]//check that json structure is correct

        personJsonJsResultOption match {
          case personSuccessOption: JsSuccess[Option[Person]] => { //json is correct
val personOption = personSuccessOption.getOrElse(None) //why would getOrElse return None??
            personOption match {
              case Some(person) => {
...              }
              case None =>{ //I am not sure when this will be triggered.
     ...
                }
              }
            }
          }
          case e: JsError => {
        ...
            }
          }
        }
      })
      .getOrElse(//body is not json
...)
    }
  }

回答1:

validateOpt by design considers success to be not only when body provides actual Person but also when Person is null or not provided. Note how documentation explains why JsSuccess(None) is returned:

  /**
   * If this result contains `JsNull` or is undefined, returns `JsSuccess(None)`.
   * Otherwise returns the result of validating as an `A` and wrapping the result in a `Some`.
   */
  def validateOpt[A](implicit rds: Reads[A]): JsResult[Option[A]]

Seems like your requirement is that Person must always be provided to be considered successful, so in this case validate should be used instead of validateOpt.