玩! Scala案例类验证

时间:2016-02-15 10:38:27

标签: scala validation playframework-2.0 bean-validation

我有一个像这样定义的控制器:

  def registerCompany = Action.async(BodyParsers.parse.json) { request =>
    request.body.validate[Company].fold(
      errors => Future {
        BadRequest(errors.mkString)
      },
      company => Future {
        registrationService.registerCompany
        Ok("saved")
      }
    )
  }

公司是一个简单的案例类

case class Company(name: String, address: Address, adminUser: Option[User] = None,
                   venues: Option[Set[Venue]] = None, _id: Option[Long]) {
}

这样我就可以利用

implicit val companyFormatter = Json.format[Company]

到目前为止一切顺利,但现在我想在公司课上进行验证。我一直在谷歌搜索,我找到的最好的是:

http://koff.io/posts/292173-validation-in-scala/

这么多解决方案,但我对其中任何一个都不满意。大多数这些解决方案都有已知的局限性或者有点混乱。我希望进行声明性验证(基于注释),因为这意味着我编写的代码更少,看起来更清晰。

我可以将java与scala混合使用JSR-303,但它不适用于案例类,我也不想为简单对象实现读写。

这是我能找到的最接近我想要的东西,但它不支持NotNull:https://github.com/bean-validation-scala/bean-validation-scala

看起来有点像奢侈品问题,有这么多不同的解决方案,但事实是,在Java中,我可以充分利用这两个世界。

还有什么我可以使用的吗?或者我在这里列出的可能性是否允许我使用基于注释的验证和案例类?

2 个答案:

答案 0 :(得分:0)

这完全取决于验证的含义。

您在请求正文中提供了验证Json的示例,我认为您希望验证Json request(使用公司约束)但不是case class Company(尽管该主题称为“Scala案例类验证” )。所以你需要使用Validation with Reads

例如,您可以使用:

  1. (__ \“name”)。读取[String] for Required constraint。
  2. (__ \“_ id”)。读取[长](min(0)keepAnd max(150))0< x< 150约束。
  3. 您可以实施自己的Reads[Company]Writes[Company],但不能实现宏Json.format[Company]

    评论更新“不同之处在于您很少需要编写自定义反序列化程序,因为jackson知道如何处理任何对象”

    如果您不希望实现自己的反序列化并希望使用format宏,则可以实现Company validation,但仍使用Reads

    val f(company: Company): Boolean = {... company constraints to boolean ...}
    
    request.body.validate[Company](
      companyFormatter.filter(ValidationError("Company validation error"))(f)
    )
    

    但是这个约束将在完整的公司反序列化后应用。

    甚至不知道哪个更好:通用反序列化和“发布”约束或自己的反序列化和“预先”约束。但两者都有效。

答案 1 :(得分:0)

你也可以自己滚动,如下所示: https://gist.github.com/eirirlar/b40bd07a71044d3776bc069f210798c6

它将验证案例类和不完整的案例类(使用键标记的类型选项的列表,其中类型和键与案例类匹配)。

它不会给你注释,但你可以自由地为不同的上下文声明不同的验证器。