如何在Jackson自定义反序列化器中抛出可被外层捕获的自定义异常
问题原因
Jackson默认启用DeserializationFeature.WRAP_EXCEPTIONS配置,会将反序列化过程中抛出的异常统一包装为JsonMappingException,对于直接继承IOException的自定义异常,默认包装逻辑不会将原始自定义异常填充为JsonMappingException的cause,因此外层无法通过getCause()获取到自定义异常实例。
解决方案一:调整反序列化器抛出逻辑(无全局配置变更,推荐)
直接在抛出自定义异常时,手动构造JsonMappingException并传入自定义异常作为cause,自定义反序列化器代码修改如下:
@Override public MyClass deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException { CustomException customEx = new CustomException("TestException", 1); // 手动包装自定义异常为JsonMappingException,填充cause throw new JsonMappingException(jsonParser, customEx.getMessage(), customEx); }
外层捕获后即可从cause中获取自定义异常:
catch (JsonMappingException e) { if (e.getCause() instanceof CustomException) { CustomException customEx = (CustomException) e.getCause(); // 业务逻辑处理,可直接获取自定义异常的code字段 int code = customEx.getCode(); } }
解决方案二:关闭Jackson异常包装全局配置
如果你希望反序列化器抛出的IOException直接透传到外层,不需要Jackson包装,可以给ObjectMapper关闭DeserializationFeature.WRAP_EXCEPTIONS配置:
ObjectMapper mapper = new ObjectMapper(); // 关闭异常自动包装配置 mapper.configure(DeserializationFeature.WRAP_EXCEPTIONS, false);
配置后外层可以直接捕获到原始的CustomException:
try { MyClass myClass = mapper.readValue(json, MyClass.class); } catch (CustomException e) { // 直接处理自定义异常 int code = e.getCode(); } catch (IOException e) { // 处理其他IO异常 }
注意事项
- 示例代码中
new ObjectMapped()是笔误,正确类名是ObjectMapper - 关闭全局异常包装后,所有反序列化过程中抛出的IOException都会直接透传,不会被包装为
JsonMappingException,需要评估对现有逻辑的影响
内容的提问来源于stack exchange,提问作者John
相关产品推荐
相关产品推荐

