2012-05-23 4 views
14

Ich habe ein Problem mit der @Valid Annotation von JSR-303. Die annotation funktioniert gut für den normalen Listen oder und Sätze, aber ich versuche, Karten zu validieren, die Listen enthalten, das heißtSo validieren Sie Sammlungen in Karten

@Valid 
HashMap<String, ArrayList<Object1>> map; 

In diesem Fall Instanzen Object1 Klasse werden nicht validiert. Gibt es eine bequeme Möglichkeit, dies rekursiv zu tun, ohne über jedes Objekt zu iterieren und es manuell zu validieren?

Antwort

13

Die Spezifikation gibt das Validierungsverhalten nicht an, wenn die Kartenwerte selbst Listen sind.

Von JSR 303 specification:

Jedes Objekt vom Iterator zur Verfügung gestellt validiert. Für Map wird der Wert jedes Map.Entry validiert (der Schlüssel wird nicht validiert).

Da der Wert in Ihrem Fall eine Liste ist, die keine Annotation @Valid hat, wird sie nicht verarbeitet. Um dies zu umgehen, können Sie entweder:

Die enthaltene Liste in eine andere Bean umbrechen, wodurch die Annotationsverarbeitung in die Liste gezwungen wird.

public class ListHolder<T extends Iterable> { 
    @Valid 
    public T wrappedList; 
} 

Oder alternativ können Sie eine custom validator schreiben Sie Ihre komplexe Karten zu handhaben. So etwas wie das:

@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; 
    } 
} 
+0

Ja, ich habe versucht, einen benutzerdefinierten Validator zu schreiben, aber um das tatsächliche Objekt zu valitieren, muss ich den Typ kennen. Setzen Sie > constraintViolations = validator.validate (Auto); – liecno

+0

Sie können Platzhalter für den generischen Typ verwenden. Sehen Sie die Antworten zu meiner Antwort für ein Beispiel, wie Sie Ihren Validator einrichten. – Perception