JsValue中validate和validateOpt的区别

Difference between validate and validateOpt in JsValue

JsValue 有两种方法

def validate[A](implicit rds: Reads[A]): JsResult[A] - 尝试将节点转换为 JsResult[T](成功或错误)。

def validateOpt[A](implicit rds: Reads[A]): JsResult[Option[A]] - 我想它也会做同样的事情。

什么情况下会用到validateOpt?在我看来,如果 JsResult 失败,那么我会得到 JsError 中的错误。那么在 JsSuccess 中增加一层 Option 有什么意义,因为 JsSuccessJsValue 成功转换为类型 A 后将始终包含值?

validateOpt 应在空值 JSON 或缺少 JSON 路径不被视为错误时使用。例如,假设我们有以下模型

case class Person(
  name: String
  employer: Option[String]
)

其中 employer 字段是可选的,因为一个人不被雇用是完全合理的,而他们总是有名字。然后反序列化下面的JSON

{
  "name": "Picard"
}

即使缺少 employer 路径也应该成功。因此手动定义 Reads[Person] 会像这样使用 validateOpt

  implicit val personRead: Reads[Person] = Reads { json =>
    for {
      name     <- (json \ "name").validate[String]
      employer <- (json \ "employer").validateOpt[String]
    } yield Person(name, employer)
  }

也对比null的反序列化,例如

  val raw = "null"
  val json = Json.parse(raw)
  println(json.validate[String])
  println(json.validateOpt[String])

应该输出

JsError(List((,List(JsonValidationError(List(error.expected.jsstring),WrappedArray())))))
JsSuccess(None,)

我们看到 validateOpt 结果成功。