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?
Validate the parameters inside the map For the validation of your Map following a specific mapping you will need a custom validator. As this may be the usecase for some, validation of @RequestParam can be done using org. springframework. validation annotations, e.g.
A Map is an object that maps keys to values. A map cannot contain duplicate keys: Each key can map to at most one value. It models the mathematical function abstraction.
The map interface is present in java. util package represents a mapping between a key and a value. The Map interface is not a subtype of the Collection interface.
A map contains values on the basis of key, i.e. key and value pair. Each key and value pair is known as an entry. A Map contains unique keys. A Map is useful if you have to search, update or delete elements on the basis of a key.
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;
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With