【问题标题】:Catching exception while converting HTTP request data into enum将 HTTP 请求数据转换为枚举时捕获异常
【发布时间】:2018-11-17 01:10:44
【问题描述】:

我在使用自定义 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() 方法中抛出自定义异常)。

【问题讨论】:

  • 您的请求是如何定义的? (您的端点)
  • @VeselinDavidov 添加了
  • 视情况而定。在您的应用程序的正常过程中,您会期待未知的颜色吗?如果是这样,您最好为此定义一个枚举常量。如果不是,则在 fromCode 方法中抛出异常是正确的,因为这是意外行为。
  • 分享信封到详情

标签: java spring-boot jackson json-deserialization


【解决方案1】:

对于@ControllerAdvice 异常处理程序中的捕获异常,试试这个:

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

}

【讨论】:

    【解决方案2】:

    您可以为类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());
            }
        }
    
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-08-21
      • 2021-01-04
      • 2021-06-12
      • 1970-01-01
      相关资源
      最近更新 更多