繁体   English   中英

Play2 / Scala自定义JSON字段验证

[英]Play2/Scala Custom JSON field validation

假设我有这个模型,在其中定义了具有特定JSON格式的自定义案例类IPAddress地址。 此类包含IPv4的String表示形式,并且在构造函数中进行了验证,如果输入字符串无效,则该构造函数将引发IllegalArgumentException。

case class Node(id: UUID, name: String, ip: IPAddress)

case class IPAddress(s: String) {
  val rx = """^([01]?\d\d?|2[0-4]\d|25[0-5])\.([01]?\d\d?|2[0-4]\d|25[0-5])\.([01]?\d\d?|2[0-4]\d|25[0-5])\.([01]?\d\d?|2[0-4]\d|25[0-5])$""".r
  require(rx.pattern.matcher(s).matches())

  val ip = s
  override def toString = ip
}


object JsonNodeFormat {
  import play.api.libs.json.Json

  implicit val midWrite: Writes[FMMid] = Writes {
    (mid: FMMid) => JsString(mid.toString)
  }
  implicit val midRead: Reads[FMMid] = JsPath.read[String].map(FMMid(_))

  implicit val NodeFormat = Json.format[Node]
}

然后,让我的控制器执行一个操作,该操作将创建一个新的Node并将其写入数据库(在我的情况下,我使用的是ReactiveMongo,但这无关紧要)

class Nodes extends Controller with MongoController {
  def collection: JSONCollection = db.collection[JSONCollection]("nodes")

  import models._
  import models.JsonNodeFormat._

  def createTest = Action.async(parse.json) {
    request =>
      request.body.validate[Node].map {
        node =>
          collection.insert(node).map {
            lastError =>
              Created(s"Node Created")
          }
      }.getOrElse(Future.successful(BadRequest("invalid json")))
  }
}

如果使用有效的json发出请求

{
    "id": "0879d4be-78bb-4cc0-810b965b",
    "ip": "192.168.0.10",
    "name": "node1"
}

一切正常。 该对象已正确添加到数据库中。 我希望控制器在传递无效的IP地址时返回BadRequest响应。 相反,如果我通过一个带有无效IP地址的Json

{
    "id": "0879d4be-78bb-4cc0-810b965b",
    "ip": "192.168.0.foo",
    "name": "node1"
}

它会导致内部服务器错误,并在控制台上打印所有堆栈(因为没有人捕获构造函数异常)。 我希望当传递无效的IPAddress时,request.body.validate函数将失败,并且执行将落在getOrElse语句中。

另请注意,传递无效的UUID不会产生错误,而是会产生BadRequest答复。

我的IPAddress类中缺少什么?

最终我找到了解决方案。 我发现在其他Reads验证助手之间,有一个称为模式的字符串与正则表达式匹配。 所以我将Json Reads更改为

  implicit val midRead: Reads[FMMid] = JsPath.read[String](pattern("""^5\.([01]?\d\d?|2[0-4]\d|25[0-5])\.([01]?\d\d?|2[0-4]\d|25[0-5])\.([01]?\d\d?|2[0-4]\d|25[0-5])$""".r)).map(FMMid(_))

一切开始按我的预期进行。

如果没有任何自定义验证器,PS仍然无法理解UUID的工作方式。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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