Пользовательское исключение времени выполнения десериализации Джексона было заключено в JsonMappingException - PullRequest
1 голос
/ 13 июля 2020

У меня есть настраиваемый десериализатор, ожидайте CustomRuntimeException, когда id не является типом String, но исключение было заключено в 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

1 Ответ

0 голосов
/ 14 июля 2020

Вы можете отключить функцию DeserializationFeature.WRAP_EXCEPTIONS :

Функция, которая определяет, должен ли Jackson код перехватывать и переносить Исключения (но never Errors!) , чтобы добавить дополнительную информацию о местонахождении (в пределах ввода) проблемы или нет. Если этот параметр включен, большинство исключений будет перехвачено и повторно выбрано (исключение, в частности, то, что исключения 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)
...