使用自定义com.fasterxml.jackson.databind.JsonDeserializer
反序列化器实现将HTTP请求值反序列化为枚举时遇到问题:
public class EnvelopeColorJsonDeserializer extends JsonDeserializer<EnvelopeColor> {
@Override
public EnvelopeColor deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
String val = p.getValueAsString();
return EnvelopeColor.fromCode(val);
}
}
这是我将值转换为枚举的方式:
public static EnvelopeColor fromCode(String code) {
Assert.notNull(code, "code");
for (EnvelopeColor type : values()) {
if (code.equals(type.code)) {
return type;
}
}
throw new RuntimeException("Not supported color: " + code);
}
端点:
@PostMapping("/")
public @ResponseBody
ResponseEntity add(@RequestBody EnvelopeDto envelope) {
// some stuff goes here...
}
问题
有没有办法如何a)检查HTTP请求值是否有效枚举常量值在进行反序列化过程之前或b)如何在@ControllerAdvice
异常处理程序中捕获异常? (我想避免在fromCode()
方法中抛出自定义异常。)
答案 0 :(得分:1)
您可以为类HttpMessageNotReadableException
添加异常处理程序。
当Spring无法将有效负载反序列化为DTO时,抛出此异常。
@ExceptionHandler(org.springframework.http.converter.HttpMessageNotReadableException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
protected @ResponseBody handleIncorrectData(HttpMessageNotReadableException ex,
HttpServletRequest request, HttpServletResponse response){
....
}
此外,您可以定义一个自定义EnumConverter
,它会向用户提供正确的枚举值。
public class CustomEnumConverter extends EnumConverter {
@Override
public Object unmarshal(HierarchicalStreamReader reader,
UnmarshallingContext context) {
try {
return super.unmarshal(reader, context);
} catch (IllegalArgumentException e) {
String inputValue = reader.getValue();
Class contextType = context.getRequiredType();
StringBuilder sb = new StringBuilder();
Object[] enumConstants = contextType.getEnumConstants();
for (Object o : enumConstants) {
sb.append(o + ",");
}
if (sb.length() > 0)
sb.deleteCharAt(sb.length() - 1);
throw new InvalidArgumentException(ErrorCode.INVALID_ARGUMENT, inputValue,
reader.getNodeName(), sb.toString());
}
}
}
答案 1 :(得分:-1)
对于@ControllerAdvice异常处理程序中的catch异常,请尝试:
@ControllerAdvice
@Order(Ordered.HIGHEST_PRECEDENCE)
public class ApplicationExceptionHandler {
private static Logger logger = LoggerFactory.getLogger(ApplicationExceptionHandler.class);
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ExceptionHandler({RuntimeException.class})
public @ResponseBody Response<Error> handleIllegalArgumentException(Exception e) {
logger.error("BadRequestException :: ", e);
return new Response<Error>(new Error("BadRequestException", e.getMessage()));
}
}