我有以下scala代码,用于将我的JSON解析为我的案例类UserLocation
。
此处usLocationDuration
或nonUSLocationDuration
是可选的;但我想要的是一种方法来强制JSON需要usLocationDuration
或nonUSLocationDuration
,而不是两者都不需要?
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)
}
}
答案 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