Bean Validation - 构造函数/工厂参数

时间:2015-03-31 08:43:06

标签: java jackson bean-validation jersey-2.0 hibernate-validator

我有一个dto对象,它使用第一个和最后一个字段保存IP范围。使用dropwizard(jersey-jackson-hibernate验证器)使用此类进行简单的CRUD操作

public class IpRangeDto {

  @JsonCreator
  public static IpRangeDto fromCidr(@JsonProperty("cidr") String cidr) {
      //Resolve CIDR and assign first and last fields
  }

  @NotNull
  @IpAddress  // My custom validator
  private String first;

  @NotNull
  @IpAddress
  private String last;
}

为了方便用户,我决定添加另一种创建此对象的方法,即使用CIDR。因此,客户端可以发送JSON中的firstlast字段,也可以只发送cidr字段。所以这样做的方法如上所述,使用@JsonCreator。它运作得很好。

"ipRange":{
  "first": "15.0.0.1",
  "last": "15.0.0.255",
}

"ipRange":{
  "cidr": "15.0.0.0/24"
}

我想验证此CIDR值是否为正确格式,以便我可以返回422并显示正确的错误消息。如果我在构造函数/工厂方法中抛出异常,则jersey-jackson直接返回400(即使我抛出ConstraintViolationException,它由JsonProcessingException封装。)

我可以简单地忽略异常,并将字段留空,因为@NotNull约束而返回422但是错误消息不会像它应该的那样清晰。

我尝试在@Cidr参数旁边添加@JsonProperty验证程序,但这似乎并不有效。我的理解是在杰克逊完成创建Dtos之后进行验证,因此使用@JsonCreator方法可能无法解决此问题。所以我也愿意重构建议。

1 个答案:

答案 0 :(得分:1)

我不是关于将Bean Validation与jackson完全集成的专家,但我认为它只是在进行实际的属性验证。这意味着正如您已经指出的那样,首先创建实体,然后验证属性。

Bean Validation(从版本1.1开始)也提供了所谓的方法验证,在这种情况下,您可以将Cidr约束放在方法的字符串参数上,但如上所述,我不认为那里杰克逊为此而整合。

还有一件事;-) - 静态方法和属性通常从Bean验证中的验证中排除(另请参阅http://beanvalidation.org/1.1/spec/#d0e2815)。

关于解决方法,有一件事情会浮现在脑海中(即使感觉有点复杂)。编写自定义类级IpRange约束。在类约束中,您将传递一个IpRangeDto实例,由您来验证整个对象并为任何违规选择正确的错误消息。如果你要在调用fromCidr时设置的dto中添加一个cidr属性,那么你将获得验证和选择正确错误消息所需的所有信息。