【问题标题】:Jackson customized deserialize runtime exception been wrapped with JsonMappingExceptionJackson 自定义的反序列化运行时异常被 JsonMappingException 包裹
【发布时间】:2020-07-13 04:05:32
【问题描述】:

我有一个定制的反序列化器,当id 不是String 类型时,期望CustomRuntimeException,但在我的测试结果中,异常被JsonMappingException 包裹。在我将jackson-databind 模块从2.5.x 升级到2.10.x 之前,测试用例运行良好。但它失败了:

java.lang.Exception: 意外异常, 预期<CustomRuntimeException> 但是 是<com.fasterxml.jackson.databind.JsonMappingException>

在我升级jackson-databind之后。

@Override
public Optional<String> deserialize(JsonParser jsonParser,
                                    DeserializationContext deserializationContext) throws IOException {

  if (jsonParser.getCurrentToken() != JsonToken.VALUE_STRING) {
    throw new CustomRuntimeException("Id should be String");
  }
  return Optional.ofNullable(jsonParser.getValueAsString());
}

CustomRuntimeException:

public class CustomRuntimeException extends RuntimeException {

    public CustomRuntimeException() {
        super("Invalid argument is provided.");
    }

    public CustomRuntimeException(String message) {
        super(message);
    }
}

测试用例:

@Test(expected = CustomRuntimeException.class)
public void shouldThrowCustomRuntimeException() throws IOException {
  objectMapper.readValue("{ \"id\": 1245672564 }", IdSchema.class);
}

堆栈跟踪:

Caused by: com.fasterxml.jackson.databind.JsonMappingException: id should be String (through reference chain: com.xxx["id"])
    at com.fasterxml.jackson.databind.JsonMappingException.wrapWithPath(JsonMappingException.java:397)
    at com.fasterxml.jackson.databind.JsonMappingException.wrapWithPath(JsonMappingException.java:356)
    at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.wrapAndThrow(BeanDeserializerBase.java:1714)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeWithErrorWrapping(BeanDeserializer.java:530)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeUsingPropertyBased(BeanDeserializer.java:417)
    at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromObjectUsingNonDefault(BeanDeserializerBase.java:1287)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:326)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:159)
    at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4218)
    at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3214)
    at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3182)
    at com.xxx.shouldThrowCustomRuntimeException(xxx.java:63)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.internal.runners.statements.ExpectException.evaluate(ExpectException.java:19)
    ... 16 more
Caused by: com.xxx.CustomRuntimeException: id should be String

【问题讨论】:

    标签: java json exception jackson jackson-databind


    【解决方案1】:

    您可以禁用功能DeserializationFeature.WRAP_EXCEPTIONS

    确定Jackson 代码是否应该捕获和包装的功能 例外(但绝不是错误!) 以添加关于 问题的位置(在输入内)与否。如果启用,大多数例外情况 将被捕获​​并重新抛出(特别是例外 IOExceptions 可以按原样传递,因为它们被声明为 可扔的);这既方便又方便,因为所有例外都是 检查和声明,因此有更多的上下文信息。 但是,有时调用应用程序可能只想取消选中“原始” 异常按原样传递。 功能默认启用

    例子:

    ObjectMapper mapper = JsonMapper.builder()
            .disable(DeserializationFeature.WRAP_EXCEPTIONS)
            .build();
    

    或者,您可以扩展 com.fasterxml.jackson.databind.JsonMappingException 而不是 RuntimeException

    class CustomRuntimeException extends JsonMappingException {
    
        public CustomRuntimeException(Closeable processor, String msg) {
            super(processor, msg);
        }
    
        public CustomRuntimeException(Closeable processor) {
            super(processor, "Invalid argument is provided.");
        }
    }
    

    并从反序列化器中以这种方式抛出:

    if (p.getCurrentToken() != JsonToken.VALUE_STRING) {
        throw new CustomRuntimeException(p, "Id should be String");
    }
    

    在这两种情况下,您都应该看到类似于:

    Exception in thread "main" com.celoxity.CustomRuntimeException: Id should be String
     at [Source: (File); line: 1, column: 9] (through reference chain: com.example.IdSchema["id"])
        at com.example.IdJsonDeserializer.deserialize(JsonTypeInfoApp.java:36)
        at com.example.IdJsonDeserializer.deserialize(JsonTypeInfoApp.java:31)
        at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:129)
        at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:288)
        at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:151)
        at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4202)
        at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3070)
    

    【讨论】:

    猜你喜欢
    • 2011-12-20
    • 1970-01-01
    • 1970-01-01
    • 2019-08-10
    • 1970-01-01
    • 2016-02-13
    • 2011-04-12
    • 2013-01-18
    • 1970-01-01
    相关资源
    最近更新 更多