billc.cn
billc.cn

Reputation: 7317

Make Hibernate Validator validate a Map by key

I am using Hibernate Validator (HV) as my JSR 303 validator. However, both in JSR 303 and in HV's extensions, there does not seem to be any annotation to specify constraints like a key must exist in a Map or only validate the Map value corresponding to a key.

My use case is that some map keys are required to have valid values only if some other property of the bean is set to true. Currently, I used a fake getter and a @AssertTrue annotation, but I'd really like to make this more annotation based.

Upvotes: 5

Views: 7891

Answers (1)

Gunnar
Gunnar

Reputation: 18990

There does not seem to be any annotation to specify constraints like a key must exist in a Map.

This can be solved by implementing a custom constraint:

@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER })
@Retention(RUNTIME)
@Documented
@Constraint(validatedBy = { ContainsKeyValidator.class })
public @interface ContainsKeys {
    String message() default "{com.acme.ContainsKey.message}";
    Class<?>[] groups() default { };
    Class<? extends Payload>[] payload() default { };
    String[] value() default {};
}

And a validator like this:

public class ContainsKeysValidator implements ConstraintValidator<ContainsKeys, Map<?, ?>> {

    String[] requiredKeys;

    @Override
    public void initialize(ContainsKeys constraintAnnotation) {
        requiredKeys = constraintAnnotation.values();
    }

    @Override
    public boolean isValid(Map<?, ?> value, ConstraintValidatorContext context) {
        if( value == null ) {
            return true;
        }

        for( String requiredKey : requiredKeys ) {
            if( value.containsKey( requiredKey ) ) {
                return false;
            }
        }

        return true;
    }
}

My use case is that some map keys are required to have valid values only if some other property of the bean is set to true.

For this requirement you could implement a class-level constraint, which allows to access the complete bean with all its attributes in the validator implementation.

Upvotes: 5

Related Questions