我们假设我们有以下JSON代码段...
{
"name": "Joe",
"surname": "Cocker",
"email": "joe.cocker@gmail.com"
}
...并想验证它:
object MyObject {
def validate(jsValue: JsValue) = myReads.reads(jsValue)
private val myReads: Reads[(String, String, String)] = (
(__ \ 'name).read[String] ~
(__ \ 'surname).read[String] ~
(__ \ 'email).read(email)
) tupled
}
myReads.reads(jsValue)
返回JsFailure
或JsSuccess(("Joe", "Cocker", "joe.cocker@gmail.com"))
...但如果成功,我不希望我的输入JSON转换为元组...我只想验证它并保持原样。这可能吗?
答案 0 :(得分:4)
所以,听起来你想要Reads[JsValue]
?
object MyObject {
def validate(jsValue: JsValue) = myReads.reads(jsValue)
private val myReads: Reads[JsValue] =
(__ \ 'name).read[String] ~>
(__ \ 'surname).read[String] ~>
(__ \ 'email).read(email) ~>
implicitly[Reads[JsValue]]
}
为了解释这里发生了什么,~>
运算符是andKeep
的别名,这实际上意味着“如果以前的操作成功,请应用以下操作并保留其结果,但不是结果前一个“。它与~
不同,后者是and
的别名,并将两个结果与一个函数(在您的情况下,将其转换为元组)组合在一起。
and
做的另一件事是合并失败。这可能对您有用,在这种情况下,您可能希望这样做:
object MyObject {
def validate(jsValue: JsValue) = myReads.reads(jsValue)
private val myReads: Reads[JsValue] = (
(__ \ 'name).read[String] ~
(__ \ 'surname).read[String] ~
(__ \ 'email).read(email)
).tupled ~> implicitly[Reads[JsValue]]
}
这与上述不同,因为解析名称,姓氏和电子邮件的失败都被组合在一起,因此,例如,如果您只发送了name
属性,则失败对象会说{{1并且surname
丢失了,而在另一个解决方案中,它会在发现email
丢失后立即停止解析,并将其作为消息返回。
答案 1 :(得分:1)
如果您不想定义实施James答案所需的额外读者,您可以通过简单的方式完成Chris在评论中的建议:
def validate(jsValue: JsValue) = myReads.reads(jsValue) map(_=>jsValue)