1

我有一个dto对象,它使用第一个和最后一个字段来保持IP范围。简单的CRUD操作与使用dropwizard这个类(新泽西州杰克逊 - Hibernate验证)Bean验证 - 构造函数/工厂参数

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。如果我在构造函数/工厂方法中抛出异常,那么泽西 - 杰克逊直接返回400(即使我抛出ConstraintViolationException,它被封装为JsonProcessingException)。

我可以简单地忽略这些异常,并将字段留空,由于@NotNull约束,这些字段将返回422,但这样错误信息就不会像应该那样清晰。

我试着在@JsonProperty参数旁边添加我的@Cidr验证程序,但这似乎并不奏效。我的理解是验证发生在Jackson完成创建Dtos后,因此使用我的@JsonCreator方法可能没有解决此问题的方法。所以我也开放重构建议。

回答

1

我不是一个将Bean Validation精确集成到杰克逊中的专家,但我认为它只是在进行实际属性验证。这意味着如您已经指出的那样,首先创建实体,然后对属性进行验证。

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

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

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