Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Howto validate Collections in Maps

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?

like image 638
liecno Avatar asked May 23 '12 15:05

liecno


People also ask

How do you validate a Map in Java?

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.

What is Map in collection?

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.

Is Map part of Java collection?

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.

Why do we use Map in Java?

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.


1 Answers

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;
   }
}
like image 152
Perception Avatar answered Sep 20 '22 13:09

Perception