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])
}
}
如何验证 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])
}
}