Проверка строки Java с использованием значений перечисления и аннотации
Я хочу проверить строку на набор значений с помощью аннотации.
Что я хочу, в основном это
@ValidateString(enumClass=com.co.enum)
String dataType;
int maxValue;
int minValue;
int precision;
или
@ValidateString(values={"String","Boolean", "Integer"})
String dataType;
int maxValue;
int minValue;
int precision;
Я также хочу сделать некоторую проверку на другие переменные в зависимости от значения, установленного в dataType,
если (DATATYPE = "String" ) maxValue, minValue, точность должна быть нулевой или нулевой.
Я не могу придумать способ добиться этого путем пользовательских аннотаций.
,
.
Кто-нибудь, пожалуйста, помогите мне
Ответы
Ответ 1
Это то, что я сделал.
Аннотация
public @interface ValidateString {
String[] acceptedValues();
String message() default "{uk.dds.ideskos.validator.ValidateString.message}";
Class<?>[] groups() default { };
Class<? extends Payload>[] payload() default { };
}
Класс проверки
public class StringValidator implements ConstraintValidator<ValidateString, String>{
private List<String> valueList;
@Override
public void initialize(ValidateString constraintAnnotation) {
valueList = new ArrayList<String>();
for(String val : constraintAnnotation.acceptedValues()) {
valueList.add(val.toUpperCase());
}
}
@Override
public boolean isValid(String value, ConstraintValidatorContext context) {
if(!valueList.contains(value.toUpperCase())) {
return false;
}
return true;
}
}
И я использовал его как
@ValidateString(acceptedValues={"Integer", "String"}, message="Invalid dataType")
String dataType;
Long maxValue;
Long minValue;
Теперь мне нужно выяснить, как реализовать условную проверку
то есть. если String, то maxValue и minValue должны быть нулевыми или нулевыми.
Любые идеи?
Ответ 2
Итак, вот код, использующий валидацию Spring и отлично подходит для меня.
Полный код приведен ниже.
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import javax.validation.Constraint;
import javax.validation.Payload;
import javax.validation.ReportAsSingleViolation;
import javax.validation.constraints.NotNull;
@Documented
@Constraint(validatedBy = EnumValidatorImpl.class)
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
@NotNull(message = "Value cannot be null")
@ReportAsSingleViolation
public @interface EnumValidator {
Class<? extends Enum<?>> enumClazz();
String message() default "Value is not valid";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
Реализация вышеуказанного класса:
import java.util.ArrayList;
import java.util.List;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
public class EnumValidatorImpl implements ConstraintValidator<EnumValidator, String> {
List<String> valueList = null;
@Override
public boolean isValid(String value, ConstraintValidatorContext context) {
if(!valueList.contains(value.toUpperCase())) {
return false;
}
return true;
}
@Override
public void initialize(EnumValidator constraintAnnotation) {
valueList = new ArrayList<String>();
Class<? extends Enum<?>> enumClass = constraintAnnotation.enumClazz();
@SuppressWarnings("rawtypes")
Enum[] enumValArr = enumClass.getEnumConstants();
for(@SuppressWarnings("rawtypes")
Enum enumVal : enumValArr) {
valueList.add(enumVal.toString().toUpperCase());
}
}
}
ИСПОЛЬЗОВАНИЕ ВЫШЕГО АННОТАЦИИ ОЧЕНЬ ПРОСТОНО
@JsonProperty("lead_id")
@EnumValidator( enumClazz=DefaultEnum.class,message="This error is coming from the enum class", groups = {Group1.class })
private String leadId;
Ответ 3
Отметьте строковое представление и сделайте реальное перечисление.
public enum DataType {
STRING,
BOOLEAN,
INTEGER;
}
Таким образом, вы избегаете выполнения сравнения строк предыдущей переменной String dataType
, чтобы определить, находится ли она в перечислении. В стороне, это также делает невозможным присвоение недействительного значения переменной-члену dataType
, и поскольку перечисления гарантированно являются синглтонами внутри загрузчика классов, это также сохраняет объем памяти.
Это стоит усилий, чтобы изменить код для использования перечислений. Однако, предполагая, что вы не можете, вы можете по крайней мере изменить аннотацию, чтобы использовать перечисления.
@ValidateString(DataType.STRING) String dataType;
и, таким образом, ваша аннотация ValidateString
по крайней мере получает выгоду от перечислений, даже если остальная часть кода не делает.
Теперь, когда вы очень редко не можете использовать перечисление, вы можете установить статические общедоступные целые числа, которые отображают каждое принятое значение.
public class DataType {
public static final int STRING = 1;
public static final int BOOLEAN = 2;
...
}
Однако, если вы используете параметр String для аннотации, у нас нет системы проверки типов, которая распространяется на тип, чтобы указать, что разрешены только определенные значения. Другими словами, Java не имеет возможности сделать что-то вроде этого:
public int<values=[1,3,5,7..9]> oddInt;
который выдает ошибку, если вы попытаетесь назначить
oddInt = 4;
Почему это важно? Поскольку, если он не применяется к обычной Java, то он не может применяться к перечислению, которое реализуется в обычных классах Java.
Ответ 4
Я принимаю ответ раджива Сингла fooobar.com/questions/343544/..., просто чтобы оптимизировать код и позволить параметру String быть нулевым, если в вашем приложении это не является обязательным и может быть пустым:
1- Удалите аннотацию @NotNull в интерфейсе
2- См. модифицированный код ниже для реализации.
public class EnumValidatorImpl implements ConstraintValidator <EnumValidator,String> {
private List<String> valueList = null;
@Override
public boolean isValid(String value, ConstraintValidatorContext context) {
return null == value || valueList.contains(value.toUpperCase());
}
@Override
public void initialize(EnumValidator constraintAnnotation) {
valueList = new ArrayList<>();
Class<? extends Enum<?>> enumClass = constraintAnnotation.enumClass();
Enum[] enumValArr = enumClass.getEnumConstants();
for(Enum enumVal : enumValArr) {
valueList.add(enumVal.toString().toUpperCase());
}
}
}
Ответ 5
Вот подробный пример с функцией динамического сообщения об ошибке
документация Hibernate
https://docs.jboss.org/hibernate/validator/4.1/reference/en-US/html/validator-customconstraints.html#validator-customconstraints-simple
Ответ 6
Немного импровизации с Java 8 Stream API
import static java.util.stream.Collectors.toList;
import static java.util.stream.Stream.of;
import java.util.List;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
public class EnumValidatorImpl implements ConstraintValidator<EnumValidator, String>
{
private List<String> valueList = null;
@Override
public boolean isValid(String value, ConstraintValidatorContext context) {
return valueList.contains(value.toUpperCase());
}
@Override
public void initialize(EnumValidator constraintAnnotation) {
valueList = of(constraintAnnotation.enumClazz().getEnumConstants()).map(e->e.toString()).collect(toList());
}
}
Ответ 7
Вы можете использовать аннотацию @NotNull
в сочетании с вашим.
Для этого вам нужно добавить аннотацию @Target( { ANNOTATION_TYPE })
в ValidateString
.
http://docs.jboss.org/hibernate/validator/4.0.1/reference/en/html/validator-customconstraints.html