Playframework [Scala]:加载json需要fieldA或fieldB,而不是两者都不需要

时间:2018-03-28 19:10:12

标签: json scala playframework

我有以下scala代码,用于将我的JSON解析为我的案例类UserLocation

此处usLocationDurationnonUSLocationDuration是可选的;但我想要的是一种方法来强制JSON需要usLocationDurationnonUSLocationDuration,而不是两者都不需要?

import play.api.libs.functional.syntax._
import play.api.libs.json._

final case class UserLocation(username: String, usLocationDuration: Option[Int], nonUSLocationDuration: Option[Int])

object UserLocation {
  implicit val userReads: Reads[UserLocation] = (
    (JsPath \ "username").read[String] and
    (JsPath \ "usLocationDuration").readNullable[Int] and
    (JsPath \ "nonUSLocationDuration").readNullable[Int]
  ) (UserLocation.apply _)

  def main(args: Array[String]): Unit = {
    val json = s"""{"username": "rs", "usLocationDuration": 10}"""
    val user = Json.parse(json).as[UserLocation]
    println(user)
  }
}

1 个答案:

答案 0 :(得分:1)

解决这个问题的一种方法是使用Either类型。请参阅play-scala-json-format-for-either

在你的情况下:

import play.api.libs.functional.syntax._
import play.api.libs.json.Reads._
import play.api.libs.json._

final case class UserLocation(username: String, locationDuration: Either[Int, Int])


object UserLocation {

  implicit val userReads: Reads[UserLocation] = (
    (JsPath \ "username").read[String] and
      ((JsPath \ "usLocationDuration").read[Int].map(dur => Left(dur): Either[Int, Int]) or
        (JsPath \ "nonUSLocationDuration").read[Int].map(dur => Right(dur): Either[Int, Int]))
    ) (UserLocation.apply _)

}

你可以用以下方法测试:

  println(Json.parse("""
                       | {
                       |   "username": "admin"
                       |   , "usLocationDuration": 123
                       | }
                     """.stripMargin).validate[UserLocation])

  println(Json.parse("""
                       | {
                       |   "username": "admin"
                       |   , "nonUSLocationDuration": 123
                       | }
                     """.stripMargin).validate[UserLocation])

  println(Json.parse("""
                       | {
                       |   "username": "admin"
                       | }
                     """.stripMargin).validate[UserLocation])

这会给你:

JsSuccess(UserLocation(admin,Left(123)),)
JsSuccess(UserLocation(admin,Right(123)),)
JsError(List((/usLocationDuration,List(JsonValidationError(List(error.path.missing),WrappedArray()))), (/nonUSLocationDuration,List(JsonValidationError(List(error.path.missing),WrappedArray())))))

点击此处查看整个示例: ScalaFiddle