Guy Wald
Guy Wald

Reputation: 599

@Pattern annotation on List of Strings

I am using javax.validation.constraints.Pattern.

The pojo i'm adding the pattern also contains a List object. How can I add the @Pattern annotation so it would check the elements?

@NotNull
private List<String> myListOfStrings;

Thanks

Upvotes: 4

Views: 15845

Answers (3)

L&#233;o Schneider
L&#233;o Schneider

Reputation: 2295

I am using kotlin, and mark_o answer doesn't work in my case. Following Nikos answer my whole custom implementation is:

@Target(AnnotationTarget.FIELD, AnnotationTarget.VALUE_PARAMETER)
@Retention
@Constraint(validatedBy = [ListPatternValidator::class])
annotation class ListPattern(val message: String = "Invalid input",
                             val regexp: String,
                             val groups: Array<KClass<*>> = [],
                             val payload: Array<KClass<out Payload>> = [])

class ListPatternValidator : ConstraintValidator<ListPattern, List<String>> {

    var pattern: String? = null

    override fun initialize(constraintAnnotation: ListPattern) {
        pattern = constraintAnnotation.regexp
    }

    override fun isValid(values: List<String>, context: ConstraintValidatorContext): Boolean {
        val regex = pattern?.toRegex() ?: return false
        return values.all { regex.matches(it) }
    }
}

Upvotes: 0

mark_o
mark_o

Reputation: 2508

See Container element constraints. With Bean Validation 2.0 you should be able to add your constraints to type arguments. In your case, you'll have:

@NotNull
private List<@Pattern(regexp="pattern-goes-here") String> myListOfStrings;

Upvotes: 11

Nikos Paraskevopoulos
Nikos Paraskevopoulos

Reputation: 40298

If instead of String you had some custom object, annotating the List with @Valid and expressing the rules in the custom object would do the trick.

For this case (you cannot express validations in the String class) I believe the best chance is a custom validator to apply a pattern on a list of strings:

@NotNull
@ListPattern("regexp")
private List<String> myListOfStrings;

The annotation would roughly look like:

@Constraint(validatedBy=ListPatternValidator.class)
@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER })
@Retention(RUNTIME)
public @interface ListPattern {
    ... // standard stuff
}

And the validator:

public class ListPatternValidator
    implements ConstraintValidator<ListPattern, List<?>> {

    public void initialize(ListPattern constraintAnnotation) {
        // see Pattern implementation
    }

    public boolean isValid(List<?> value, ConstraintValidatorContext context) {
        for( Object o : value ) {
            if( does not match ) return false;
        }
        return true;
    }
}

Upvotes: 2

Related Questions