Jackson 字段的条件验证

Jackson Conditional Validation of a field

我正在尝试使用以下结构在 Spring 上设置范围查询结构:

public class QueryRange extends Query {

    @JsonProperty(required = true)
    @NotBlank
    @NotNull
    private String field;

    private Object gt;

    private Object gte;

    private Object lt;

    private Object lte;

    public String getField() {
         return field;
    }

    public QueryRange setField(String field) {
        this.field = field;
        return this;
    }

    public Object getGt() {
        return gt;
    }

    public QueryRange setGt(Object gt) {
        this.gt = gt;
        return this;
    }

    public Object getGte() {
        return gte;
    }

    public QueryRange setGte(Object gte) {
        this.gte = gte;
        return this;
    }

    public Object getLt() {
        return lt;
    }

    public QueryRange setLt(Object lt) {
        this.lt = lt;
        return this;
    }

    public Object getLte() {
        return lte;
    }

    public QueryRange setLte(Object lte) {
        this.lte = lte;
        return this;
    }

    @AssertTrue(message = "Invalid range. A value for 'gt' or 'lt' should be set.")
    private boolean isRangeSpecified() {
        return this.gt != null || this.lt != null;
    }

    @AssertTrue(message = "Invalid range data type. 'gt' and 'lt' must be of the same type.")
    private boolean isRangeDataTypeValid() {
        if (this.gt != null && this.lt != null) {
            return this.gt.getClass().equals(this.lt.getClass());
        }

        return true;
    }
}

问题是值 gt、gte、lt 或 lte 中至少有一个不应该为空。我该如何验证?

我已经像上面的代码示例一样尝试了 Bean Validation,但没有成功。有什么建议吗?

您应该使用 Class-level 约束。

Last but not least, a constraint can also be placed on the class level. In this case not a single property is subject of the validation but the complete object. Class-level constraints are useful if the validation depends on a correlation between several properties of an object.

@ValidQueryRange
public class QueryRange extends Query {
    // your class here...
    private Object gt;

    private Object gte;

    private Object lt;

    private Object lte;
}

@Target({ TYPE, ANNOTATION_TYPE })
@Retention(RUNTIME)
@Constraint(validatedBy = { ValidQueryRangeValidator.class })
@Documented
public @interface ValidQueryRange {

    String message() default "{error}";

    Class<?>[] groups() default { };

    Class<? extends Payload>[] payload() default { };
}

public class ValidQueryRangeValidator implements ConstraintValidator<ValidQueryRange, QueryRange> {

    @Override
    public void initialize(ValidQueryRange constraintAnnotation) {
    }

    @Override
    public boolean isValid(QueryRange queryRange, ConstraintValidatorContext context) {
        if ( queryRange == null ) {
            return true;
        }
        // put your logic here
        if ( queryRange.getGt() == null || queryRange.getLt() == null) {
            return false;
        }

        return true;
    }
}