Я пытаюсь создать класс с java.lang.Exception
, хранящимся в качестве поля. Также я пытаюсь исключить трассировку стека из сериализации / десериализации с использованием аннотации @JsonIgnoreProperties
.
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.IOException;
class ExWrapper {
@JsonIgnoreProperties({"stackTrace"})
public Exception ex;
@Override
public String toString() {
return "ExWrapper{" +
"ex=" + ex +
'}';
}
}
public class Example {
public static void main(String[] args) throws IOException {
ObjectMapper mapper = new ObjectMapper();
ExWrapper exw = new ExWrapper();
exw.ex = new Exception("Oops");
String str = mapper.writeValueAsString(exw);
System.out.println(str);
ExWrapper exW = mapper.readValue(str, ExWrapper.class);
System.out.println(exW);
}
}
Ошибка результата довольно удивительна, Джексон не может найти поле message
:
Exception in thread "main" com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "message" (class java.lang.Exception), not marked as ignorable (one known property: "cause"])
at [Source: (String)"{"ex":{"cause":null,"message":"Oops","suppressed":[],"localizedMessage":"Oops"}}"; line: 1, column: 32] (through reference chain: ExWrapper["ex"]->java.lang.Exception["message"])
at com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException.from(UnrecognizedPropertyException.java:61)
at com.fasterxml.jackson.databind.DeserializationContext.handleUnknownProperty(DeserializationContext.java:840)
at com.fasterxml.jackson.databind.deser.std.StdDeserializer.handleUnknownProperty(StdDeserializer.java:1179)
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.handleUnknownProperty(BeanDeserializerBase.java:1592)
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.handleUnknownVanilla(BeanDeserializerBase.java:1570)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:375)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:159)
at com.fasterxml.jackson.databind.deser.impl.FieldProperty.deserializeAndSet(FieldProperty.java:138)
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:3205)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3173)
at Example.main(Example.java:25)
Ну, в классе Throwable
есть только getMessage
, а setMessage
нет, так что это кажется немного разумным, если вы не попытаетесь удалить аннотацию @JsonIgnoreProperties
. Он работает как чудо: он сериализует и десериализует обратно должным образом, и отсутствие установщика для message
внезапно не является проблемой. Добавление "message"
к пропущенным полям также заставляет его работать (но без сообщения об исключении).
Я попытался произвольно войти в код Джексона с помощью отладчика и обнаружил, что при отсутствии @JsonIgnoreProperties
в конечном итоге ThrowableDeserializer
Методы вызываются и не вызываются, когда присутствует аннотация. ThrowableDeserializer
, похоже, имеет некоторые хаки, специфичные для сообщения об исключенииЯ предполагаю, что ThrowableDeserializer
нежизнеспособен, когда отсутствует трассировка стека, и Джексон возвращается к сериализатору Java-бина по умолчанию.
Вопрос в том, что именно здесь происходит и как его решить.