web-dev-qa-db-ja.com

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に設定された値に応じて、他の変数の検証も行いたいと思います。

if(dataType = "String")maxValue、minValue、precisionはすべてnullまたはゼロでなければなりません。

カスタムアノテーションによってこれを実現する方法は考えられません。 。

誰か助けてください

25
Joe

これは私がやったことです。

注釈

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はnullまたはゼロでなければなりません。

何か案は?

23
Joe

そこで、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());
    }

  }

}

上記の注釈の使用IS非常に簡単

 @JsonProperty("lead_id")
  @EnumValidator( enumClazz=DefaultEnum.class,message="This error is coming from the enum class", groups = {Group1.class })
  private String leadId;
30
Rajeev Singla

文字列表現を捨てて、実際の列挙を行います。

public enum DataType {
   STRING,
   BOOLEAN,
   INTEGER;
}

そうすれば、以前のString dataType変数の文字列比較を行って、それが列挙型であるかどうかを判断する必要がなくなります。余談ですが、無効な値をメンバー変数dataTypeに割り当てることもできません。また、enumはクラスローダー内でシングルトンであることが保証されているため、メモリフットプリントも節約できます。

列挙型を使用するようにコードを変更することは価値があります。ただし、できないと仮定すると、少なくとも列挙型を使用するように注釈を変更できます。

@ValidateString(DataType.STRING) String dataType;

そうすれば、コードの残りが恩恵を受けない場合でも、少なくともValidateStringアノテーションは列挙型の恩恵を受けます。

列挙をまったく使用できないという非常にまれな機会に、受け入れられた各値をマップする静的パブリック整数を設定できます。

public class DataType {
  public static final int STRING = 1;
  public static final int BOOLEAN = 2;
  ...
}

ただし、注釈パラメーターに文字列を使用する場合、特定の値のみが許可されることを指定するために型に拡張する型チェックシステムはありません。つまり、Javaには次のようなことをする機能がありません。

public int<values=[1,3,5,7..9]> oddInt; 

割り当てようとするとエラーがスローされます

 oddInt = 4;

何でこれが大切ですか?通常のJavaに適用されない場合、通常のJavaクラスで実装される列挙に適用できないためです。

8
Edwin Buck

Rajeev Singlaの応答を取り上げます https://stackoverflow.com/a/21070806/8923905 空にすることができます:

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

    }
}
0
Emmanuel H

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

Hibernateドキュメンテーションによる動的エラーメッセージの機能を備えた詳細な例を次に示します。

https://docs.jboss.org/hibernate/validator/4.1/reference/en-US/html/validator-customconstraints.html#validator-customconstraints-simple

0
Chen