使用枚举值和注释的 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 all should be null or zero
}
我想不出通过自定义注释来实现此目的的方法。
有人请帮助我。
I want to validate a string against a set of values using annotations.
What I want is basically this:
@ValidateString(enumClass=com.co.enum)
String dataType;
int maxValue;
int minValue;
int precision;
or
@ValidateString(values={"String","Boolean", "Integer"})
String dataType;
int maxValue;
int minValue;
int precision;
I also want to do some validation on other variables depending upon the value set in dataType
:
if (dataType = "String") {
// maxValue, minValue, precision all should be null or zero
}
I can't think of a way to achieve this by custom annotations.
Somebody please help me.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(10)
我知道我来晚了一点(确切地说晚了 11 年),但我仍然愿意做出贡献。
这里提供的答案很好,它们在大多数情况下解决了问题,但在我看来,它们缺乏个性化的触感。
我是什么意思?
所有解决方案都会创建
ConstraintValidator
并在其中实现验证逻辑。这很好,它解决了问题,但是,如果我想通过枚举的 toString() 进行比较,或者更好,我想通过名称进行比较,会发生什么,两个不同的比较。为此,有必要为所需的每种比较类型实现一个 ConstraintValidator,而实际上它们的逻辑非常相似。
在我的特定情况下,一个非常旧的系统进行了比较,一些与
toUpperCase
进行比较,另一些与toLoweCase
进行比较,另一些与trim
进行比较,一些与name
,其他则使用toString
,完全混乱,而我们的想法是将所有这些概括为相同的行为。我向您展示的解决方案将 @Rajeev 的出色答案与必要的自定义相结合,以便能够重用 ConstraintValidator 并为每个不同的枚举仅实现一种比较方法。
总体思路:让emun实现一个接口来规范比较。
首先,@annotation,没什么花哨的:
请记住,枚举类将出现在
target
字段中。现在是概括行为的接口:
这两个元素的一般组合会产生一个枚举,其中包含概括的比较行为,如果它发生变化,只会影响所述实现,而不会影响系统的其他元素。
最后是
ConstraintValidator
,这就是“魔法”发生的地方。注意:
lombok
依赖项用于@Slf4j
以便轻松记录日志,并使用springframework
的Assert
来验证空值。它的使用就像预期的一样简单:
这样,如果您有另一个带有另一个比较逻辑的枚举,那么就像使用其嵌入逻辑创建所述枚举一样简单,例如:
这样
ConstraintValidator
就是在所有应用程序中重用,并且更改只会影响负责它们的类,而不会破坏系统逻辑的其余部分。不管你相信与否,这个解决方案保证了我的加薪,我希望我能为你做类似的事情。 :+1:
I know I'm a little late to the party (11 years late to be exact), but I'd still like to contribute.
The answers presented here are great, they solve the problem in most cases, but in my opinion they lack the personalization touch.
What do I mean?
All solutions create the
ConstraintValidator<EnumValidator, String>
and implement the validation logic in it.And that is great, it solve the problem, but, what happens if I want to make the comparison by the toString() of the enum, or better, I have another one that I want to compare by the name, two different comparisons. For this, it would be necessary to implement a
ConstraintValidator
for each type of comparison that is needed, when in fact their logic is VERY similar.In my particular case, a very old system had comparisons, some with
toUpperCase
, others withtoLoweCase
, others withtrim
, some withname
, others withtoString
, total chaos, and the idea was to generalize all this in the same behavior.The solution that I present to you combines the excellent answer of @Rajeev with the necessary customization to be able to reuse the
ConstraintValidator
and implement only one comparison method for each different enum.The general idea: Make the emun implement an interface to standardize the comparison.
First of all, the @annotation, nothing fancy:
Keep in mind that the enum class will be presented in the
target
field.Now the interface to generalize the behavior:
A general combination of these two elements results in an enum with the generalized comparison behavior inside it, which in case it changes would only affect said implementation and no other elements of the system.
Finally the
ConstraintValidator
, this is where the 'magic' happens.Note:
lombok
dependencies are used for@Slf4j
for easy logging andspringframework
'sAssert
for validations of null value.its use is as simple as expected:
In this way, if you have another enum with another comparison logic, it is as simple as creating said enum with its embedded logic, like:
And this way the
ConstraintValidator
it's reused along all application, and changes only affect the class responsible for them without breaking the rest of the system logic.Believe it or not this solution guaranteed me a raise at work, I hope I do something similar for you. :+1:
我采纳 Rajeev Singla 的回复 https://stackoverflow.com/a/21070806/8923905,只是为了优化代码和允许 String 参数为 null,如果在您的应用程序中它不是强制的并且可以为空:
1- 删除接口上的 @NotNull 注释
2- 请参阅下面的修改代码用于实现。
I take up Rajeev Singla's response https://stackoverflow.com/a/21070806/8923905, just to optimize the code and allow the String parameter to be null, if in your application it is not mandatory and can be empty :
1- Remove the @NotNull annotation on the Interface
2- See the modified code below for the implementation.
这是一个具有动态错误消息功能的详细示例
通过 Hibernate 文档
https://docs.jboss.org/hibernate/validator/4.1/reference/en-US/html/validator-customconstraints.html#validator-customconstraints-simple
Here is a detailed example with the feature of a dynamic error message
by Hibernate Documentation
https://docs.jboss.org/hibernate/validator/4.1/reference/en-US/html/validator-customconstraints.html#validator-customconstraints-simple
我也想补充我的两分钱。
在建议的解决方案中,枚举类型成员被替换为字符串,以便能够使用 (javax|jakarta).validation 来验证它。
我在同样的思考中挣扎,宁愿不将枚举属性更改为字符串,而是拦截 Jackson 抛出的 InvalidFormatException。
我正在使用 Spring boot 休息控制器,因此异常是由控制器建议捕获的。
该解决方案是用 Kotlin 编写的。
I would like to add my two cents too.
In the proposed solutions the enum type member is replaced with a string to enable using (javax|jakarta).validation for validating it.
I struggled with the same contemplation and had rather not change my enum attributes to strings, instead intercept the InvalidFormatException thrown by Jackson.
I'm using Spring boot rest controllers, and so the exception is caught by a controller advice.
The solution is written in Kotlin.
您可以将
@NotNull
注释与您的注释结合使用。要使用它,您需要在
ValidateString
中添加@Target( { ANNOTATION_TYPE })
注释。http://docs.jboss.org /hibernate/validator/4.0.1/reference/en/html/validator-customconstraints.html
You can use
@NotNull
annotation in conjunction with yours.To use that you need to add
@Target( { ANNOTATION_TYPE })
annotation inValidateString
.http://docs.jboss.org/hibernate/validator/4.0.1/reference/en/html/validator-customconstraints.html
这是使用 Spring 验证的代码,对我来说非常有用。
完整代码如下。
@EnumValidator注解定义:
上述类的实现:
上述注解的用法非常简单
So here is the code being using Spring validation and works great for me.
Full code is given below.
@EnumValidator annotation definition:
Implementation of the above class:
Usage of the above annotation is very simple
这就是我所做的。
注释
验证类
我使用它就像
现在我需要弄清楚如何实现条件检查
IE。如果是字符串,那么 maxValue 和 minValue 应该为 null 或零..
有什么想法吗?
This is what I did.
Annotation
Validation Class
And i used it like
Now I need to figure out how to implement conditional check
ie. if String then maxValue and minValue should be null or Zero..
Any ideas?
放弃字符串表示形式,并进行真正的枚举。
这样,您就不必对先前的 String dataType 变量进行字符串比较来确定它是否在枚举中。顺便说一句,它也使得不可能为成员变量 dataType 分配无效值,并且由于枚举在类加载器中保证是单例,因此它还节省了内存占用。
更改代码以使用枚举是值得的。但是,假设您不能,您至少可以更改注释以使用枚举。
这样你的 ValidateString 注释至少可以从枚举中受益,即使代码的其余部分没有。
现在,在极少数情况下您根本无法使用枚举,您可以设置静态公共整数,它映射每个接受的值。
但是,如果您使用字符串作为注释参数,我们就没有类型检查系统来扩展类型以指定仅允许特定值。换句话说,Java 缺乏执行以下操作的能力:
则会抛出错误。
如果您尝试分配“为什么这很重要?”, 因为如果它不适用于常规 Java,那么它就不能适用于常规 Java 类中实现的枚举。
Ditch the String representation, and do a real enum.
That way you avoid ever having to do string comparison of the previous
String dataType
variable to determine if it is in the enum. As an aside, it also makes it impossible to assign a non-valid value to the member variabledataType
and since enums are guaranteed to be singletons within the class loader, it also saves on memory footprint.It's worth the effort to change your code to use enums. However, assuming that you can't, you can at least change the annotation to use enums.
and that way your
ValidateString
annotation at least gets to benefit from enums, even if the rest of the code doesn't.Now on the extremely rare chance that you can't use an enumeration at all, you can set static public integers, which map each accepted value.
However, if you use a String for the annotation parameter, we don't have a type checking system which extends into the type to specify that only particular values are allowed. In other words, Java lacks the ability to do something like this:
which would throw an error if you attempted to assign
Why is this important? Because if it doesn't apply to regular Java, then it cannot apply to the enumeration which is implemented in regular Java classes.
我对 kotlin 的尝试:
My attempt for a kotlin one:
使用 Java 8 Stream API 进行一点即兴创作
Little bit of improvisation with Java 8 Stream API