播放:如何验证Json

播放:如何验证Json,json,scala,playframework,Json,Scala,Playframework,假设我们有以下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)] = ( (__ \

假设我们有以下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被转换成元组。。。我只想验证它并保持原样。这可能吗?

那么,听起来你想要一个
读[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]]
}
为了解释这里发生的情况,
~>
操作符是
和keep
的别名,其本质是指“如果上一个操作成功,则应用以下操作并保留其结果,但不保留上一个操作的结果”。它不同于
~
,后者是
的别名,它将两个结果与一个函数组合在一起(在您的例子中,将其转换为元组)

所做的另一件事是合并故障。这实际上可能对您有用,在这种情况下,您可能希望执行以下操作:

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
属性,则失败对象将表示缺少
name
email
,而在另一个解决方案中,它会在发现
姓氏
丢失时立即停止解析,并将其作为消息返回。

因此,听起来您希望
读取[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]]
}
为了解释这里发生的情况,
~>
操作符是
和keep
的别名,其本质是指“如果上一个操作成功,则应用以下操作并保留其结果,但不保留上一个操作的结果”。它不同于
~
,后者是
的别名,它将两个结果与一个函数组合在一起(在您的例子中,将其转换为元组)

所做的另一件事是合并故障。这实际上可能对您有用,在这种情况下,您可能希望执行以下操作:

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
属性,则失败对象将表示缺少
name
email
,而在另一个解决方案中,一旦发现
姓氏
丢失,它将停止解析,并将其作为消息返回。

如果您不想定义实现James答案所需的额外读取器,您可以按照Chris在评论中的建议,使用一个简单的:

def validate(jsValue: JsValue) = myReads.reads(jsValue) map(_=>jsValue)

如果你不想定义实现James答案所需的额外读者,你可以按照Chris在评论中的建议做一个简单的:

def validate(jsValue: JsValue) = myReads.reads(jsValue) map(_=>jsValue)

你不能直接调用myReads.reads(jsValue),检查是否成功,然后扔掉结果吗?你不能直接调用myReads.reads(jsValue),检查是否成功,然后扔掉结果吗?是的,我想要错误,映射将保留JsFailures,但它将删除已解析的json,并用Jssuccess中包装的原始值替换它是的,我想要错误,映射将保留JsFailures,但它将删除已解析的json,并用Jssuccess中包装的原始值替换它