Reputation: 934
I have a problem with the @Valid
annotation of JSR-303. The annotation works fine for normal lists or and sets, but I am trying to validate Maps which contain Lists, i.e.
@Valid
HashMap<String, ArrayList<Object1>> map;
In this case, instances of Object1
class are not validated. Is there a convenient way to do this recursively, without iterating over every object and validating it manually?
Upvotes: 16
Views: 10956
Reputation: 80603
The specification does not specify the validation behavior when the map values are themselves lists.
From JSR 303 specification:
Each object provided by the iterator is validated. For Map, the value of each Map.Entry is validated (the key is not validated).
Since the value in your case is a list, which does not have a @Valid annotation, it does not get processed. To get around this you can either:
Wrap the contained list in another bean, forcing the annotation processing onto the list.
public class ListHolder<T extends Iterable> {
@Valid
public T wrappedList;
}
Or alternatively you can write a custom validator to handle your complex maps. Something like this:
@Target({ METHOD, FIELD, ANNOTATION_TYPE })
@Retention(RUNTIME)
@Documented
@Constraint(validatedBy = ValidMapValidator.class)
public @interface ValidMap {
String message() default "valid.map";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
public class ValidMapValidator implements
ConstraintValidator<ValidMap, Map<?, ?>> {
@Override
public void initialize(final ValidMap annotation) {
return;
}
@Override
public boolean isValid(final Map<?, ?> map,
final ConstraintValidatorContext context) {
if (map == null || map.size() == 0)
return true;
// Iterate each map entry and validate
return true;
}
}
Upvotes: 14