scala play json 自定义验证 oneOf

scala play json custom validation oneOf

如何验证 json 其中 2 个键之一是强制性的。

Ex1: 有效 Json

{
    "userName": "MyName",
    "userId": 123
}

Ex2:有效Json

{
    "userName": "MyName"
}

Ex3: 有效 Json

{
    "userId": 123
}

Ex4: InValid Json - 缺少用户名和用户 ID

{
    "email": "email@email.com"
}

我的案例class如下

case class FindUser(userName: Option[String], userId: Option[Int]
object FindUser {
  implicit val findUserReads = Json.reads[FindUser]
}

控制器:

request.body.validate[FindUser]

作为解决方案之一,您可以实施自己的 def reads(json: JsValue): JsResult[A]:

import play.api.libs.json._

case class FindUser(userName: Option[String], userId: Option[Int])

object FindUser {
  implicit val findUserReads: Reads[FindUser] = new Reads[FindUser] {
    override def reads(json: JsValue): JsResult[FindUser] = {
      // Read and validate `userName` node
      val nameJsRes: JsResult[Option[String]] = (json \ "userName").validateOpt[String]
      // Read and validate `userId`
      val idJsRes: JsResult[Option[Int]] = (json \ "userId").validateOpt[Int]

      // For-comprehension which will fail fast
      // It will give JsError if:
      //  - nameJsRes is invalid
      //  - idJsRes is invalid
      //  - name and is are empty
      for {
        name <- nameJsRes
        id <- idJsRes
        result <- if (name.isEmpty && id.isEmpty) {
          JsError(JsonValidationError("Either `userName` or `userId` must be set"))
        }
        else {
          JsSuccess(FindUser(name, id))
        }
      } yield result
    }
  }

  def main(args: Array[String]): Unit = {
    // JsSuccess(FindUser(Some(123),Some(1123)),)
    println(Json.parse(
      """{
        |    "userName": "123",
        |    "userId": 1123
        |}""".stripMargin).validate[FindUser])

    // JsSuccess(FindUser(None,Some(1123)),)
    println(Json.parse(
      """{
        |    "userNameXXX": "123",
        |    "userId": 1123
        |}""".stripMargin).validate[FindUser])

    // JsSuccess(FindUser(Some(123),None),)
    println(Json.parse(
      """{
        |    "userName": "123",
        |    "userIdXXX": 1123
        |}""".stripMargin).validate[FindUser])

    // JsError(List((,List(JsonValidationError(List(Either `userName` or `userId` must be set),WrappedArray())))))
    println(Json.parse(
      """{
        |    "userNameXXX": "123",
        |    "userIdXXX": 1123
        |}""".stripMargin).validate[FindUser])
  }
}