org.springframework.validation.Errors
无法捕获枚举反序列化错误 我有一个rest控制器,它使用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);
}
}
我的课程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;
}
我的枚举类MySimpleEnum
基本上是具有两个值的类:
public enum MySimpleEnum{
ORC("ORC"),
URUK("URUK");
private String value;
MySimpleEnum(String value) {
this.value = value;
}
@Override
public String toString() {
return String.valueOf(value);
}
}
当该对象位于Error
或String
上时,此对象的验证(以及在springframework 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 ,枚举或 springframework错误,以便在控制器主体中捕获并使用此异常? / p>
答案 0 :(得分:0)
发生的问题是,在枚举MySimpleEnum中没有常量“ HOBBIT”,可能是“ ORC”和“ URUK”,在验证问题中可以像示例中那样简单地使用:
@NotNull(message = "Custom message")
private MySimpleEnum aSimpleEnum
答案 1 :(得分:0)
我最终做了类似的事情来提取请求中有问题的字段:
int start = ex.getMessage().indexOf("[\"");
int end = ex.getMessage().indexOf("\"]");
String fieldName = exception.getMessage().substring(start + 2, end)
该字段恰好位于括号之间的消息末尾。
我并不为那件事感到骄傲,这很麻烦,但这似乎是枚举的唯一方法。
我想最好使用字符串和适当的Spring验证,因为它过多地依赖于实现,并且可能在将来的更新中失效。
答案 2 :(得分:0)
我只是遇到了同样的问题,但不喜欢给用户提供未经格式化的“丑陋”的验证错误消息的想法。
首先,我使pojo上的enum属性不可为空。
@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消息上的枚举值进行硬编码,但是在这种特殊情况下(少量的枚举值),它比默认的枚举序列化错误消息更可取,并且具有以下行为:关闭隔离的错误消息。
我考虑了一个自定义验证器,但是开始感到沉重。也许有人可以对此进行改进。