Play框架:如何在解析JSON时验证可选字段

时间:2015-12-16 21:15:22

标签: json scala playframework

给出以下JSON ......

{
     "nickname": "mj",
     "firstname": "Mike",
     "lastName": "Jordan",
     "trash": "ignore"
}

...我需要解析并验证它以便

  1. 除了nicknamefirstNamelastName之外的任何字段都会被过滤掉 - 在上面的示例中,trash必须删除
  2. 如果已定义,nickname(可选)必须至少包含3个字符
  3. 以下是我的代码:

    import play.api.libs.json._
    import play.api.libs.functional.syntax._
    
    def orEmpty = reads | __.json.put(Json.obj())    
    
    val js = Json.parse("""{ "nickname": "mj", "firstname": "Mike", "lastName": "Jordan" }""")
    
    val validateUser = (
      ((__ \ 'nickname).json.pickBranch(Reads.of[JsString] <~ Reads.minLength[String](3)) orEmpty) ~
      ((__ \ 'firstName).json.pickBranch) ~
      ((__ \ 'lastName).json.pickBranch)
    )
    
    validateUser.reads(js).fold(
      valid = { validated => JsSuccess(js) },
      invalid => { errors => JsError(errors) }
    )
    

    问题是,如果nickname无效,因为短于3个字符,orEmpty适用,并且不会报告任何错误。我需要的是保持nickname可选(这就是我定义orEmpty的原因),但是当定义时,当且仅当nickanme通过Reads.minLength时,验证才会成功检查。

1 个答案:

答案 0 :(得分:2)

假设Play Framework 2.4.x.我认为在2.3.x中阅读可空字段有点不同但是它的想法是一样的。

如果您认为JSON验证器和变换器实际上只是Reads[T <: JsValue],那么理由更容易。

总的来说,您需要考虑的是nickname字段实际上是可选的,您需要表示它。基本上,您要找的是将nullableReadsReads.minLength一起撰写,将昵称读作Option[String]

因此,您可以将要验证的结构表示为:

case class ToValidate(nickname: Option[String], firstname: String, lastname: String)

并定义你是读者:

import play.api.libs.json._
import play.api.libs.json.Reads._
import play.api.libs.functional.syntax._

implicit val toValidateReads: Reads[ToValidate] = (
  (__ \ "nickname").readNullable[String](minLength(3)) ~
  (__ \ "firstname").read[String] ~
  (__ \ "lastname").read[String]
)(ToValidate.apply _)

然后你可以改变你的意见:

val js = Json.parse("""{ "nickname": "mj", "firstname": "Mike", "lastname": "Jordan" }""")
val v = js.validate[ToValidate]
println(v) // JsError(List((/nickname,List(ValidationError(List(error.minLength),WrappedArray(3))))))