使用 Jackson 序列化/反序列化异常而不使用堆栈跟踪

我正在尝试创建一个具有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);

    }

}

好吧,类中只有getMessage和没有,所以这似乎有点合理,除非您尝试删除注释。它的工作原理就像一个魅力:它可以正确地序列化和反序列化回来,并且缺少 setter for突然就不再是问题了。添加到忽略的字段也可以使其工作(但没有异常消息)。setMessageThrowable@JsonIgnorePropertiesmessage"message"

我尝试使用调试器随机步入 Jackson 代码,发现当@JsonIgnoreProperties缺少时,最终ThrowableDeserializer会调用方法,而当注释存在时不会调用它们。ThrowableDeserializer似乎有一些特定于异常消息的技巧。我的猜测是,ThrowableDeserializer当堆栈跟踪丢失并且 Jackson 回退到默认的 java bean 序列化器时,这是不可行的。

问题是这里到底发生了什么以及如何解决它。


HUH函数
浏览 129回答 1
1回答

阿波罗的战车

版本2ThrowableDeserializer类扩展,BeanDeserializer因此这两个共享一些如何创建和反序列化POJO. Exception不是常规的POJO,应该以不同的方式处理。由于它没有提供许多设置器,我们需要使用构造函数来使用消息和其他我们可以跳过的字段来创建它。要注册构造函数,我们可以使用MixIn功能:import com.fasterxml.jackson.annotation.JsonCreator;import com.fasterxml.jackson.annotation.JsonIgnoreProperties;import com.fasterxml.jackson.annotation.JsonProperty;import com.fasterxml.jackson.databind.ObjectMapper;import java.io.File;public class JsonPathApp {    public static void main(String[] args) throws Exception {        File jsonFile = new File("./resource/test.json").getAbsoluteFile();        ObjectMapper mapper = new ObjectMapper();        mapper.addMixIn(Exception.class, ExceptionMixIn.class);        mapper.addMixIn(Throwable.class, ThrowableMixIn.class);        ExWrapper exW = mapper.readValue(jsonFile, ExWrapper.class);        exW.ex.printStackTrace();    }}@JsonIgnoreProperties("stackTrace")abstract class ExceptionMixIn extends Exception {    @JsonCreator    public ExceptionMixIn(@JsonProperty("message") String message) {        super(message);    }}@JsonIgnoreProperties("stackTrace")abstract class ThrowableMixIn extends Throwable {    @JsonCreator    public ThrowableMixIn(@JsonProperty("message") String message) {        super(message);    }}class ExWrapper {    public Exception ex;    @Override    public String toString() {        return "ExWrapper{" +                "ex=" + ex +                '}';    }}JSON上面的带有原因的异常代码打印:java.lang.Exception: Opps    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)    at java.lang.reflect.Constructor.newInstance(Constructor.java:422)    at com.fasterxml.jackson.databind.introspect.AnnotatedConstructor.call(AnnotatedConstructor.java:124)    at com.fasterxml.jackson.databind.deser.std.StdValueInstantiator.createFromObjectWith(StdValueInstantiator.java:283)    at com.fasterxml.jackson.databind.deser.ValueInstantiator.createFromObjectWith(ValueInstantiator.java:229)    at com.fasterxml.jackson.databind.deser.impl.PropertyBasedCreator.build(PropertyBasedCreator.java:195)    at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeUsingPropertyBased(BeanDeserializer.java:422)    at com.fasterxml.jackson.databind.deser.std.ThrowableDeserializer.deserializeFromObject(ThrowableDeserializer.java:65)    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:4013)    at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2902)Caused by: java.lang.Throwable: Root oops    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)    at java.lang.reflect.Constructor.newInstance(Constructor.java:422)    at com.fasterxml.jackson.databind.introspect.AnnotatedConstructor.call(AnnotatedConstructor.java:124)    at com.fasterxml.jackson.databind.deser.std.StdValueInstantiator.createFromObjectWith(StdValueInstantiator.java:283)    at com.fasterxml.jackson.databind.deser.ValueInstantiator.createFromObjectWith(ValueInstantiator.java:229)    at com.fasterxml.jackson.databind.deser.impl.PropertyBasedCreator.build(PropertyBasedCreator.java:195)    at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeUsingPropertyBased(BeanDeserializer.java:422)    at com.fasterxml.jackson.databind.deser.std.ThrowableDeserializer.deserializeFromObject(ThrowableDeserializer.java:65)    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:159)    at com.fasterxml.jackson.databind.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:530)    at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeWithErrorWrapping(BeanDeserializer.java:528)    at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeUsingPropertyBased(BeanDeserializer.java:449)    ... 8 more如您所见,异常具有默认值stackTrace,并且会stackTrace跳过JSON有效负载。版本1我没有深入挖掘它,但启用allowSetters解决了这个问题:@JsonIgnoreProperties(value = {"stackTrace"}, allowSetters = true)public Exception ex;进行此更改的代码将打印:{"ex":{"cause":null,"message":"Oops","localizedMessage":"Oops","suppressed":[]}}ExWrapper{ex=java.lang.Exception: Oops}
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java