使用枚举值和注释进行Java字符串验证

Joe*_*Joe 25 java enums annotations

我想使用注释针对一组值验证字符串.我想要的基本上就是这个

@ValidateString(enumClass=com.co.enum)
String dataType;

int maxValue;
int minValue;
int precision;
Run Code Online (Sandbox Code Playgroud)

要么

@ValidateString(values={"String","Boolean", "Integer"})
String dataType;

int maxValue;
int minValue;
int precision;
Run Code Online (Sandbox Code Playgroud)

我还想根据dataType中设置的值对其他变量进行一些验证,

if(dataType ="String")maxValue,minValue,precision all应为null或0.

我无法想到通过自定义注释实现这一目标的方法..

有人请帮帮我

小智 32

所以这里是使用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 {};

}
Run Code Online (Sandbox Code Playgroud)

上述课程的实施:

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) {
    return valueList.contains(value.toUpperCase());
  }

  @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());
    }

  }

}
Run Code Online (Sandbox Code Playgroud)

使用上面的注释非常简单

 @JsonProperty("lead_id")
  @EnumValidator( enumClazz=DefaultEnum.class,message="This error is coming from the enum class", groups = {Group1.class })
  private String leadId;
Run Code Online (Sandbox Code Playgroud)

  • 您好组在哪里初始化? (2认同)

Joe*_*Joe 23

这就是我做的.

注解

public @interface ValidateString {

    String[] acceptedValues();

    String message() default "{uk.dds.ideskos.validator.ValidateString.message}";

    Class<?>[] groups() default { };

    Class<? extends Payload>[] payload() default { }; 
}
Run Code Online (Sandbox Code Playgroud)

验证类

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) {
        return valueList.contains(value.toUpperCase());
    }

}
Run Code Online (Sandbox Code Playgroud)

我用它就像

@ValidateString(acceptedValues={"Integer", "String"}, message="Invalid dataType")
String dataType;

Long maxValue;
Long minValue;
Run Code Online (Sandbox Code Playgroud)

现在我需要弄清楚如何实现条件检查,即.如果String然后maxValue和minValue应为null或Zero ..

有任何想法吗?

  • 最大的缺点是,如果枚举发生更改,此注释将很快被忘记。没有办法将其映射到枚举的值吗? (2认同)

Edw*_*uck 8

抛弃String表示,并做一个真正的枚举.

public enum DataType {
   STRING,
   BOOLEAN,
   INTEGER;
}
Run Code Online (Sandbox Code Playgroud)

这样你就不必对前一个String dataType变量进行字符串比较,以确定它是否在枚举中.另外,它也使得无法为成员变量分配无效值,dataType并且因为枚举可以保证在类加载器中是单例,所以它也节省了内存占用.

更改代码以使用枚举是值得的.但是,假设您不能,您至少可以更改注释以使用枚举.

@ValidateString(DataType.STRING) String dataType;
Run Code Online (Sandbox Code Playgroud)

这样你的ValidateString注释至少可以从枚举中受益,即使代码的其余部分没有.

现在,根本不可能完全不使用枚举,可以设置静态公共整数,映射每个接受的值.

public class DataType {
  public static final int STRING = 1;
  public static final int BOOLEAN = 2;
  ...
}
Run Code Online (Sandbox Code Playgroud)

但是,如果对注释参数使用String,则我们没有类型检查系统,该系统扩展到该类型以指定仅允许特定值.换句话说,Java缺乏这样的能力:

public int<values=[1,3,5,7..9]> oddInt; 
Run Code Online (Sandbox Code Playgroud)

如果您尝试分配,则会抛出错误

 oddInt = 4;
Run Code Online (Sandbox Code Playgroud)

为什么这很重要?因为如果它不适用于常规Java,那么它不能应用于常规Java类中实现的枚举.

  • “放弃字符串表示,并进行真正的枚举。” 这对于用户输入验证来说确实是最糟糕的建议......例如,对于 http 请求,用户总是发送一个字符串。如果值不正确,用户期望得到正确的消息(例如 dataType 与任何已知值不匹配。使用其中之一...)而不是 400 BAD REQUEST,这会在真正的枚举中发生 (3认同)
  • 枚举`valueForString(...)`上的一个简单静态方法将返回Enum值,如果没有则返回null(例如,由于拼写错误).它集中了输入的验证,并在定义输入的位置进行.让我们不要过度戏剧化.这不是最糟糕的建议,因为我们都可以想出更糟糕的建议. (2认同)