使用 springframework 验证错误验证枚举
Validate an Enum with springframework validation Errors
TL;DR:枚举反序列化错误未被 Rest 控制器中的 org.springframework.validation.Errors
捕获
供参考:我们还没有找到一个干净的解决方案,因为我们最终决定,没有人应该告诉我们一个糟糕的枚举
我有一个使用 org.springframework.validation.Errors
进行参数验证的休息控制器:
@RequestMapping(value = "/vol1/frodo")
public ResponseEntity<Object> simpleMethodUsingPost(
HttpServletRequest httpServletRequest,
@Valid @RequestBody MySimpleObject simpleObject,
Errors errors) {
/* If an error occured, I need to log the object */
if (errors.hasErrors()) {
List<FieldError> fields = errors.getFieldErrors();
doSomething(fields , simpleObject);
}
}
我的 class MySimpleObject
看起来像这样:
public class MySimpleObject {
@Valid
@NotNull(message = "anObjectField is a mandatory field")
private EmbeddedObject anObjectField = null;
@Valid
@NotNull(message = "aStringField is a mandatory field")
private String aStringField = null;
@Valid
private MySimpleEnum aSimpleEnum = null;
}
而我的枚举 class MySimpleEnum
基本上是具有两个值的 class:
public enum MySimpleEnum{
ORC("ORC"),
URUK("URUK");
private String value;
MySimpleEnum(String value) {
this.value = value;
}
@Override
public String toString() {
return String.valueOf(value);
}
}
此对象的验证(以及 springframework Error
对象中的错误注入)在 String
或 Object
上运行良好,但验证失败enum
的(因此包含有效注释枚举的对象也会失败)。
在值无效时尝试将 JSON String
转换为枚举失败:
org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error:
Cannot deserialize value of type 'lotr.middleearth.model.MySimpleEnum' from String "HOBBIT"
如果我使用 ResponseEntityExceptionHandler
并覆盖 handleHttpMessageNotReadable
,则会捕获此反序列化错误,但我无法访问其他不同的参数,也无法使用它们。
如何配置 Validator、enum 或 springframework Error 以便这个异常在我的控制器主体中被捕获并可用?
出现的问题是枚举 MySimpleEnum 中没有常量 "HOBBIT" 可能性是 "ORC" 和 "URUK",在验证问题中可以简单地使用示例:
@NotNull(message = "Custom message")
private MySimpleEnum aSimpleEnum
我最终做了类似的事情来提取请求中有问题的字段:
int start = ex.getMessage().indexOf("[\"");
int end = ex.getMessage().indexOf("\"]");
String fieldName = exception.getMessage().substring(start + 2, end)
该字段恰好位于括号之间消息的末尾。
我并不为那个感到骄傲,它很乱,但它似乎是枚举的唯一方法。
我想最好改用字符串和适当的 Spring 验证,因为它在很大程度上取决于实现,并且可能会随着未来的更新而中断。
我刚遇到同样的问题,但不喜欢向用户提供未格式化的 "ugly" 验证错误消息的想法。
首先,我使枚举 属性 在 pojo 上不可为空。
@NotNull(message = "Type must be NEW_APPLICATION or RENEWAL")
private RegistrationSubmissionTypeEnum type;
然后我更改了 setter 以基本上检查输入(作为字符串)并查看它是否与枚举之一匹配。如果不是,我什么也不做,属性 保持为空,并且它作为验证错误消息之一被报告回来(使用 @NotNull 注释上使用的消息文本)。
public void setType(Object typeInput) {
for (RegistrationSubmissionTypeEnum typeEnum : RegistrationSubmissionTypeEnum.values()) {
if (typeEnum.getKey().equalsIgnoreCase(typeInput.toString())) {
this.type=RegistrationSubmissionTypeEnum.valueOf(typeInput.toString());
}
}
}
这才是关键。我们都鄙视的正常行为会生成丑陋的错误消息,但它也会以单独显示此错误消息的方式进行。就个人而言,我喜欢将所有错误一起发回。
我不喜欢在 @NotNull 消息上硬编码枚举值,但在这种特殊情况下(少量枚举值),它比默认枚举序列化错误消息更可取,并且行为one-off 孤立的错误消息。
我考虑过自定义验证器,但开始感觉很沉重。也许有人可以对此进行改进。
TL;DR:枚举反序列化错误未被 Rest 控制器中的 org.springframework.validation.Errors
捕获
供参考:我们还没有找到一个干净的解决方案,因为我们最终决定,没有人应该告诉我们一个糟糕的枚举
我有一个使用 org.springframework.validation.Errors
进行参数验证的休息控制器:
@RequestMapping(value = "/vol1/frodo")
public ResponseEntity<Object> simpleMethodUsingPost(
HttpServletRequest httpServletRequest,
@Valid @RequestBody MySimpleObject simpleObject,
Errors errors) {
/* If an error occured, I need to log the object */
if (errors.hasErrors()) {
List<FieldError> fields = errors.getFieldErrors();
doSomething(fields , simpleObject);
}
}
我的 class MySimpleObject
看起来像这样:
public class MySimpleObject {
@Valid
@NotNull(message = "anObjectField is a mandatory field")
private EmbeddedObject anObjectField = null;
@Valid
@NotNull(message = "aStringField is a mandatory field")
private String aStringField = null;
@Valid
private MySimpleEnum aSimpleEnum = null;
}
而我的枚举 class MySimpleEnum
基本上是具有两个值的 class:
public enum MySimpleEnum{
ORC("ORC"),
URUK("URUK");
private String value;
MySimpleEnum(String value) {
this.value = value;
}
@Override
public String toString() {
return String.valueOf(value);
}
}
此对象的验证(以及 springframework Error
对象中的错误注入)在 String
或 Object
上运行良好,但验证失败enum
的(因此包含有效注释枚举的对象也会失败)。
在值无效时尝试将 JSON String
转换为枚举失败:
org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error:
Cannot deserialize value of type 'lotr.middleearth.model.MySimpleEnum' from String "HOBBIT"
如果我使用 ResponseEntityExceptionHandler
并覆盖 handleHttpMessageNotReadable
,则会捕获此反序列化错误,但我无法访问其他不同的参数,也无法使用它们。
如何配置 Validator、enum 或 springframework Error 以便这个异常在我的控制器主体中被捕获并可用?
出现的问题是枚举 MySimpleEnum 中没有常量 "HOBBIT" 可能性是 "ORC" 和 "URUK",在验证问题中可以简单地使用示例:
@NotNull(message = "Custom message")
private MySimpleEnum aSimpleEnum
我最终做了类似的事情来提取请求中有问题的字段:
int start = ex.getMessage().indexOf("[\"");
int end = ex.getMessage().indexOf("\"]");
String fieldName = exception.getMessage().substring(start + 2, end)
该字段恰好位于括号之间消息的末尾。
我并不为那个感到骄傲,它很乱,但它似乎是枚举的唯一方法。
我想最好改用字符串和适当的 Spring 验证,因为它在很大程度上取决于实现,并且可能会随着未来的更新而中断。
我刚遇到同样的问题,但不喜欢向用户提供未格式化的 "ugly" 验证错误消息的想法。
首先,我使枚举 属性 在 pojo 上不可为空。
@NotNull(message = "Type must be NEW_APPLICATION or RENEWAL")
private RegistrationSubmissionTypeEnum type;
然后我更改了 setter 以基本上检查输入(作为字符串)并查看它是否与枚举之一匹配。如果不是,我什么也不做,属性 保持为空,并且它作为验证错误消息之一被报告回来(使用 @NotNull 注释上使用的消息文本)。
public void setType(Object typeInput) {
for (RegistrationSubmissionTypeEnum typeEnum : RegistrationSubmissionTypeEnum.values()) {
if (typeEnum.getKey().equalsIgnoreCase(typeInput.toString())) {
this.type=RegistrationSubmissionTypeEnum.valueOf(typeInput.toString());
}
}
}
这才是关键。我们都鄙视的正常行为会生成丑陋的错误消息,但它也会以单独显示此错误消息的方式进行。就个人而言,我喜欢将所有错误一起发回。
我不喜欢在 @NotNull 消息上硬编码枚举值,但在这种特殊情况下(少量枚举值),它比默认枚举序列化错误消息更可取,并且行为one-off 孤立的错误消息。
我考虑过自定义验证器,但开始感觉很沉重。也许有人可以对此进行改进。