I am trying to create a class with a java.lang.Exception stored as a field. Also I am trying to exclude stack trace from serialization/deserialization using @JsonIgnoreProperties annotation.
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);
    }
}
The result error is quite surprising, Jackson cannot find the message field:
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)
Well, there is only getMessage and no setMessage in Throwable class so it seems a bit reasonable unless you try to remove @JsonIgnoreProperties annotation. It works like a charm: it serializes and deserializes back properly and missing setter for message is suddenly not a problem. Adding "message" to ignored fields also make it work (yet without an exception message).
I tried to randomly step in Jackson code using debugger and found out that when @JsonIgnoreProperties is missing, eventually ThrowableDeserializer methods are called and they are not called when the annotation is present. ThrowableDeserializer seems to have some hacks specific to exception message. My guess is that ThrowableDeserializer is not viable when the stack trace is missing and Jackson falls back to default java bean serializer.
The question is what exactly is going on here and how to solve it.