杰克逊';s readEntity正在将我的异常序列化为java.lang.Throwable,而不是正确的错误异常
在我的代码中,我有一个扩展IllegalArgumentException的异常:杰克逊';s readEntity正在将我的异常序列化为java.lang.Throwable,而不是正确的错误异常,java,rest,serialization,jackson,jersey,Java,Rest,Serialization,Jackson,Jersey,在我的代码中,我有一个扩展IllegalArgumentException的异常: public class InvalidDataSourceException extends IllegalArgumentException { public InvalidDataSourceException(String message, Throwable cause) { super(message, cause); } } 在我的Jersey REST web服务中,所有错误都用
public class InvalidDataSourceException extends IllegalArgumentException {
public InvalidDataSourceException(String message, Throwable cause) {
super(message, cause);
}
}
在我的Jersey REST web服务中,所有错误都用类RESTError
包装,以便
所有rest服务都可以引发相同的异常:
public class RESTError extends Throwable {
public RESTError(Throwable cause) {
super(cause);
}
}
因此,当InvalidDataSourceException发生时,会将其作为引发RESTError
的原因抛出:
throw new RESTError(invalidDataSourceException);
我们已为Throwable对象注册了序列化程序:
public class ThrowableSerializer extends JsonSerializer<Throwable> {
@Override
public void serialize(Throwable value, JsonGenerator jgen,
SerializerProvider provider) throws IOException, JsonProcessingException {
jgen.writeStartObject();
jgen.writeStringField("class", value.getClass().getCanonicalName());
jgen.writeStringField("message", value.getMessage());
jgen.writeObjectField("stackTrace", value.getStackTrace());
jgen.writeStringField("stackTraceAsString", Throwables.getStackTraceAsString(value));
jgen.writeObjectField("cause", value.getCause());
jgen.writeEndObject();
}
}
执行此操作时,异常原因被序列化为java.lang.Throwable
,而不是我的自定义InvalidDataSourceException
。它把它扔了下来。因此,单元测试失败。为什么呢 看看javadoc
当您扩展Throwable并将另一个传递给构造函数时,它将传递给private Throwable cause
属性。这是关于类型的唯一信息。因此,在反序列化过程中,Java只知道存在类型为Throwable的属性cause
,并且不知道该属性是InvalidDataSourceException
还是其他类型
编辑:现在看起来好像缺少反序列化程序问题首先,是不是另一个Java应用程序知道存在类InvalidDataSourceException?嗨@JamesCube非常感谢您的响应。我添加了一个单元测试来重现这个问题。好了,现在它更有意义了。您有一个序列化程序,可以将类的信息转换为json,非常好。但是,你不应该有一个对称的反序列化程序吗。由于没有直接映射,这些只是字段,默认情况下Jackson只会忽略它不知道的字段(据我所知,现在可能是错误的)。您需要一个能够理解自定义可丢弃JSON的解组器。这一切到底有什么意义?我试过了。我意识到有一个内置的异常抛出反序列化程序覆盖了我的自定义反序列化程序,这是在做一些不正确的事情。我有一个
@class
,它只是忽略了它。在那之后,我放弃了,开始使用从主错误对象返回的错误代码,这样我就可以一起避免这个问题。令人失望的是,我们有一个可丢弃的序列化程序。对不起,我忘了提那件事。我用它更新了机票。我把机票编号从“jersey”改为“jackson”,因为jersey与此无关。我还添加了一个单元测试。
public class TestJsonSerializationOfExceptions {
private static final Logger log = LoggerFactory.getLogger(TestJsonSerializationOfExceptions.class);
@Test
public void testBasic() throws Exception {
ObjectMapper objectMapper = ObjectMapperFactory.create();
try {
throw new InvalidDataSourceException("test msg");
} catch (Throwable t) {
RESTError restError = new RESTError(Response.Status.INTERNAL_SERVER_ERROR, Errors.General, t);
String str = objectMapper.writeValueAsString(restError); // It is correct here!
log.info("Rest error when serialized: {}", str);
restError = objectMapper.readValue(str, RESTError.class);
Assert.assertEquals(restError.getCause().getClass(), InvalidDataSourceException.class);
}
}
}