简体   繁体   中英

Play: How to validate Json

Let's suppose we have the following JSON snippet...

{
  "name": "Joe",
  "surname": "Cocker",
  "email": "joe.cocker@gmail.com"
}

... and want to validate it:

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) returns either JsFailure or JsSuccess(("Joe", "Cocker", "joe.cocker@gmail.com")) ... but in case of success I don't want my input JSON be transformed into a tuple... I just want to validate it and keep as is. Is that possible?

So, it sounds like you want a 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]]
}

To explain what's happening here, the ~> operator is an alias for andKeep , which essentially means "if the previous operation was successful, apply the following operation and keep its result, but not the result of the previous one". It differs from ~ , which is an alias for and , in that and combines the two results together with a function (in your case, converting it to a tuple).

Another thing that and does is it merges failures. This may actually be useful to you, in which case, you may want to do this:

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]]
}

This differs from the above, in that failures from parsing name, surname and email, are all combined together, so if for example, you only sent a name property, the failure object will say that surname and email were missing, whereas in the other solution, it would stop parsing as soon as it found that surname was missing and just return that as the message.

如果您不想定义实现James答案所需的额外读者,则可以使用简单的方法来完成Chris在注释中建议的操作:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM