JsConstraints#filter 具有以下签名
def filter[A](otherwise: ValidationError)(p: A => Boolean)(implicit reads: Reads[A])
当你写作时
filter(ValidationError("error.scope.value"))(??? == JsString("user") || ??? == JsString("group")))
代码(??? == JsString("user") || ??? == JsString("group")) 实际上是要过滤的第二个参数,因此它应该是A => Boolean 的谓词。此外,由于这是在email 读取为Reads[String] 之后应用的,因此您的实际A 是String,因此您应该删除JsString。
你能写出的最小改动是:
implicit val aclRuleScopeRead = (
(__ \ "type").read[String](pattern("^(default|user|group|domain)$".r)) and
(__ \ "value").read[String](
email keepAnd
filter(
ValidationError("error.scope.value")
)(x => x == "user" || x == "group"))
).tupled
我强烈建议您将谓词提取到自己的方法中:
def isValidEmail: (String) => Boolean = {
x => x == "user" || x == "group"
}
把你的阅读写成
implicit val aclRuleScopeRead = (
(__ \ "type").read[String](pattern("^(default|user|group|domain)$".r)) and
(__ \ "value").read[String](
email keepAnd filter(ValidationError("error.scope.value"))(isValidEmail))
).tupled
你可以拥有更好的
val validEmail = email keepAnd filter(ValidationError("error.scope.value"))(isValidEmail))
然后写
implicit val aclRuleScopeRead = (
(__ \ "type").read[String](pattern("^(default|user|group|domain)$".r)) and
(__ \ "value").read[String](validEmail)
).tupled
根据 cmets 的说明,如果类型是“用户”或“组”,您只想解析电子邮件,否则返回空字符串。
答案接近this question中概述的解决方案
value字段的读取首先需要检查type字段的值。类型字段的条件如下所示:
(__ \ "type").read[String].filter(ValidationError("error.scope.value"))(isEmailType)
其中 isEmailType 定义为
def isEmailType: (String) => Boolean = { x => x == "user" || x == "group" }
如果类型是user 或group,这将返回一个读取JsSuccess,否则返回一个JsError。从 cmets 中我们知道,如果类型不是user 或group,我们应该返回空字符串,读取可以变成:
(__ \ "type").read[String]
.filter(ValidationError("error.scope.value"))(isEmailType)
.orElse Reads.pure("")
这是安全的,永远不会返回JsError。这很好,因为有一个专用的reads 来强制对type 进行验证,我们当前正在操作的读取只是作为value 验证的一部分。
现在我们需要将读取更改为解析value,如果解析是JsSuccess:
(__ \ "type").read[String]
.filter(ValidationError("error.scope.value"))(isEmailType)
.flatMap(_ => (__ \ "value").read[String](email))
.orElse Reads.pure("")
使用 flatMap,如果 type 读取成功,我们将 type 读取替换为 value 上的正确读取。