当前位置: 首页 > 知识库问答 >
问题:

JSR 303验证,如果一个字段等于“某物”,那么其他字段不应为空

朱通
2023-03-14

我想用JSR-303javax做一点自定义验证。验证

我有一块地。如果在这个字段中输入了某个值,我想要求其他几个字段不是null

我在试图弄清楚这一点。不确定我该怎么称呼它来帮助找到一个解释。

任何帮助都将不胜感激。我对这个很陌生。

目前我正在考虑一个自定义约束。但我不确定如何从注释中测试依赖字段的值。基本上,我不确定如何从注释访问panel对象。

public class StatusValidator implements ConstraintValidator<NotNull, String> {

    @Override
    public void initialize(NotNull constraintAnnotation) {}

    @Override
    public boolean isValid(String value, ConstraintValidatorContext context) {
        if ("Canceled".equals(panel.status.getValue())) {
            if (value != null) {
                return true;
            }
        } else {
            return false;
        }
    }
}

这是panel.status.getValue();给我带来了麻烦...

共有3个答案

楚灿
2023-03-14

您应该使用自定义DefaultGroupSequenceProvider

// Marker interface
public interface ConditionalValidation {}
public class MyCustomFormSequenceProvider
    implements DefaultGroupSequenceProvider<MyCustomForm> {

    @Override
    public List<Class<?>> getValidationGroups(MyCustomForm myCustomForm) {

        List<Class<?>> sequence = new ArrayList<>();

        // Apply all validation rules from ConditionalValidation group
        // only if someField has given value
        if ("some value".equals(myCustomForm.getSomeField())) {
            sequence.add(ConditionalValidation.class);
        }

        // Apply all validation rules from default group
        sequence.add(MyCustomForm.class);

        return sequence;
    }
}
@GroupSequenceProvider(MyCustomFormSequenceProvider.class)
public class MyCustomForm {

    private String someField;

    @NotEmpty(groups = ConditionalValidation.class)
    private String fieldTwo;

    @NotEmpty(groups = ConditionalValidation.class)
    private String fieldThree;

    @NotEmpty
    private String fieldAlwaysValidated;


    // getters, setters omitted
}

另请参见有关此主题的相关问题。

太叔昊苍
2023-03-14

在这种情况下,我建议编写一个自定义验证器,它将在类级别(允许我们访问对象的字段)验证只有在另一个字段具有特定值时才需要一个字段。请注意,您应该编写通用验证器,该验证器将获得两个字段名,并且只处理这两个字段。要需要多个字段,您应该为每个字段添加此验证器。

使用下面的代码作为一个想法(我还没有测试它)。

>

  • 验证器接口

    /**
     * Validates that field {@code dependFieldName} is not null if
     * field {@code fieldName} has value {@code fieldValue}.
     **/
    @Target({TYPE, ANNOTATION_TYPE})
    @Retention(RUNTIME)
    @Repeatable(NotNullIfAnotherFieldHasValue.List.class) // only with hibernate-validator >= 6.x
    @Constraint(validatedBy = NotNullIfAnotherFieldHasValueValidator.class)
    @Documented
    public @interface NotNullIfAnotherFieldHasValue {
    
        String fieldName();
        String fieldValue();
        String dependFieldName();
    
        String message() default "{NotNullIfAnotherFieldHasValue.message}";
        Class<?>[] groups() default {};
        Class<? extends Payload>[] payload() default {};
    
        @Target({TYPE, ANNOTATION_TYPE})
        @Retention(RUNTIME)
        @Documented
        @interface List {
            NotNullIfAnotherFieldHasValue[] value();
        }
    
    }
    

    验证器实现

    /**
     * Implementation of {@link NotNullIfAnotherFieldHasValue} validator.
     **/
    public class NotNullIfAnotherFieldHasValueValidator
        implements ConstraintValidator<NotNullIfAnotherFieldHasValue, Object> {
    
        private String fieldName;
        private String expectedFieldValue;
        private String dependFieldName;
    
        @Override
        public void initialize(NotNullIfAnotherFieldHasValue annotation) {
            fieldName          = annotation.fieldName();
            expectedFieldValue = annotation.fieldValue();
            dependFieldName    = annotation.dependFieldName();
        }
    
        @Override
        public boolean isValid(Object value, ConstraintValidatorContext ctx) {
    
            if (value == null) {
                return true;
            }
    
            try {
                String fieldValue       = BeanUtils.getProperty(value, fieldName);
                String dependFieldValue = BeanUtils.getProperty(value, dependFieldName);
    
                if (expectedFieldValue.equals(fieldValue) && dependFieldValue == null) {
                    ctx.disableDefaultConstraintViolation();
                    ctx.buildConstraintViolationWithTemplate(ctx.getDefaultConstraintMessageTemplate())
                        .addNode(dependFieldName)
                        .addConstraintViolation();
                        return false;
                }
    
            } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException ex) {
                throw new RuntimeException(ex);
            }
    
            return true;
        }
    
    }
    

    验证器使用示例(hibernate Validator)

    @NotNullIfAnotherFieldHasValue(
        fieldName = "status",
        fieldValue = "Canceled",
        dependFieldName = "fieldOne")
    @NotNullIfAnotherFieldHasValue(
        fieldName = "status",
        fieldValue = "Canceled",
        dependFieldName = "fieldTwo")
    public class SampleBean {
        private String status;
        private String fieldOne;
        private String fieldTwo;
    
        // getters and setters omitted
    }
    

    验证器使用示例(hibernate Validator)

    @NotNullIfAnotherFieldHasValue.List({
        @NotNullIfAnotherFieldHasValue(
            fieldName = "status",
            fieldValue = "Canceled",
            dependFieldName = "fieldOne"),
        @NotNullIfAnotherFieldHasValue(
            fieldName = "status",
            fieldValue = "Canceled",
            dependFieldName = "fieldTwo")
    })
    public class SampleBean {
        private String status;
        private String fieldOne;
        private String fieldTwo;
    
        // getters and setters omitted
    }
    

    请注意,验证器实现使用了commons BeanUtils库中的BeanUtils类,但也可以使用Spring框架中的BeanWrapperImpl

    请参阅这个伟大的答案:使用Hibernate Validator进行跨域验证(JSR 303)

  • 孟建木
    2023-03-14

    定义必须验证为true的方法,并在其顶部放置@AssertTrue注释:

      @AssertTrue
      private boolean isOk() {
        return someField != something || otherField != null;
      }
    

    方法必须以“is”开头。

     类似资料:
    • 我使用Symfony 5.3。我有一个表单,有3个字段没有映射到任何实体: "原因"-文本, use_predefined复选框 "predefined_reason"-下拉列表。 我构建的表单如下(一个片段): “原因”字段应根据需要显示在UI中,但其他两个字段不应显示。但是,在验证过程中,如果选中了复选框“预定义的原因”,则第一个字段不应为必填字段,而“预定义的原因”应为必填字段。

    • 我开始使用验证框架用jax-rs验证json请求 是否可以根据另一个字段验证一个字段? 提前致谢

    • 问题内容: 如何查询或过滤一个字段不等于另一个字段?即,其中document1.city1.name不等于document1.city2.name。 这个的一些版本? http://www.elasticsearch.org/guide/zh- CN/elasticsearch/reference/current/search-request-script- fields.html 问题答案: 是

    • 问题内容: 有没有一种方法可以使用此处定义的注释来定义Hibernate验证规则,说明至少一个字段不能为null? 这将是一个假设的示例(实际上不存在): 在所示的情况下,fieldA可以为null或fieldB可以为null,但不能同时为两者。 一种方法是创建自己的验证器,但是我想避免它已经存在。如果您已经验证过,请分享一个验证人…谢谢! 问题答案: 我终于写了整个验证器: 用法示例:

    • 问题内容: 我在想出可以验证JSON是否包含以下任一内容的JSON模式时遇到了麻烦: 仅一个字段 仅另一个领域 (其他两个字段之一) 但如果存在多个则不匹配。 具体来说,我要 和/或 进行验证,但我不想接受更多的验证。 这是到目前为止我得到的: 这比我想要的要匹配。我希望它符合以下所有条件: 但不符合: 我猜想我有明显的失踪-我想知道它是什么。 问题答案: 问题是“非”语义。“不需要”不表示“禁止

    • 我想验证字段,如果存在,将失败,如果另一个字段不存在如何做到这一点?我已经创建了自定义验证,以获得基于存储ID的记录 我有字段和,并且字段根据在最大值和最小值之间进行验证,如果我显示=且未填写字段,则验证字段将通过,并显示错误,因为我未填写我希望在执行自定义验证之前检查是否为空。。 我已经阅读了laravel文档上的所有验证方法,但仍然没有找到解决方案。怎么做?