jackson对Exception类型对象的序列化与反序列化
发现问题
今天在调试系统错误通知的时候遇到了一个问题。我们在系统异常时候要通过队列系统发送各种通知到团队内部成员。
因此我写了一个通用接口。接口中有传递Exception对象到队列中,再由队列消费者解析后生成消息发送出去。
这个Exception对象是先通过jackson序列化后再在队列消费端反序列化完成传递的。
但是在测试过程中发现,经过队列传递后的Exception对象丢失了很多信息,甚至连基本的class类型都不能还原。
比如一个IllegalArgumentException经过jackson的序列化与反序列化之后得到的是一个几乎空的Exception对象。从message到cause到stackTrace数据全部丢失。
例如:
IllegalStateException e = new IllegalStateException("abc");
String str = JSONSnakeUtils.writeValue(e);
Exception ex = JSONSnakeUtils.readValue(str, Exception.class);
注:以上代码中JSONSnakeUtils是我们自己封装的jackson方法,基本原样调用了jackson的objectMapper方法。
上面方法中ex对象已经和原来的e对象天差地别了。
尝试解决
然后我想到了使用java自带的序列化工具来实现。
经过以下测试:
IllegalStateException e = new IllegalStateException("abc");
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
ObjectOutputStream oo = new ObjectOutputStream(byteArrayOutputStream);
oo.writeObject(e);
oo.close();
byte[] bytes = byteArrayOutputStream.toByteArray();
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
ObjectInputStream ois = new ObjectInputStream(byteArrayInputStream);
Exception ex = (Exception) ois.readObject();
得到的ex对象原样还原了原始的e对象,说明这个思路是可行的。
最终方案
结合jackson自定义序列化与反序列化的方式,有了最终的解决方案:
首先定义自定义的序列化与反序列化方法,将经过ObjectOutputStream序列化后的byte数组转化为字符串通过json传递。再在消费端经过byte数组转换回Exception对象。代码如下:
定义序列化类
public class ExceptionJsonSerializer extends JsonSerializer<Exception> {
@Override
public void serialize(Exception exception, JsonGenerator gen, SerializerProvider serializers) throws IOException {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
ObjectOutputStream oo = new ObjectOutputStream(byteArrayOutputStream);
oo.writeObject(exception);
oo.flush();
oo.close();
byte[] bytes = byteArrayOutputStream.toByteArray();
gen.writeRawValue("\"" + ByteArrayUtil.toHexString(bytes) + "\"");
}
}
定义反序列化类
public class ExceptionJsonDeserializer extends JsonDeserializer<Exception> {
@Override
public Exception deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException {
String valueAsString = jsonParser.getValueAsString();
byte[] bytes = ByteArrayUtil.hexStringToByteArray(valueAsString);
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
ObjectInputStream ois = new ObjectInputStream(byteArrayInputStream);
try {
Exception ex = (Exception) ois.readObject();
return ex;
} catch (ClassNotFoundException e) {
e.printStackTrace();
return null;
} finally {
ois.close();
}
}
}
最后在对象字段上添加注解
public static class AAA {
String xxx;
String yyy;
@JsonSerialize(using = ExceptionJsonSerializer.class)
@JsonDeserialize(using = ExceptionJsonDeserializer.class)
Exception exception;
}
OK。至此问题解决。
jackson对Exception类型对象的序列化与反序列化的更多相关文章
- (记录)Jedis存放对象和读取对象--Java序列化与反序列化
一.理论分析 在学习Redis中的Jedis这一部分的时候,要使用到Protostuff(Protobuf的Java客户端)这一序列化工具.一开始看到序列化这些字眼的时候,感觉到一头雾水.于是,参考了 ...
- Java对象的序列化和反序列化[转]
Java基础学习总结--Java对象的序列化和反序列化 一.序列化和反序列化的概念 把对象转换为字节序列的过程称为对象的序列化.把字节序列恢复为对象的过程称为对象的反序列化. 对象的序列化主要有两种用 ...
- Java对象的序列化与反序列化-Json篇
说到Java对象的序列化与反序列化,我们首先想到的应该是Java的Serializable接口,这玩意在两个系统之间的DTO对象里面可能会用到,用于系统之间的数据传输.或者在RPC(远程方法调用)时可 ...
- ObjectOutputStream和ObjectInputStream对对象进行序列化和反序列化
1 Java序列化和反序列化简介 Java序列化是指把对象转换为字节序列的过程,而Java反序列化是指把字节序列恢复为java对象的过程. 我们把对象序列化成有序字节流,保存到本地磁盘或者Redis等 ...
- java中对象的序列化和反序列化
[对象的序列化和反序列化 ] 1.定义:序列化--将对象写到一个输出流中.反序列化则是从一个输入流中读取一个对象.类中的成员必须是可序列化的,而且要实现Serializable接口,这样的类的对象才能 ...
- Java对象的序列化与反序列化
序列化与反序列化 序列化 (Serialization)是将对象的状态信息转换为可以存储或传输的形式的过程.一般将一个对象存储至一个储存媒介,例如档案或是记亿体缓冲等.在网络传输过程中,可以是字节或是 ...
- 【Java IO流】对象的序列化和反序列化
对象的序列化和反序列化 1)对象序列化,就是将Object对象转换成byte序列,反之叫对象的反序列化. 2)序列化流(ObjectOutputStream),是字节的过滤流—— writeObjec ...
- 利用JavaScriptSerializer类 进行Json对象的序列化和反序列化和过滤
项目下载:JavaScriptSerializer_对JSON对象序列化与反序列化及过滤器 利用<JavascriptSerializer类> 进行Json对象的序列化和反序列化 1. 首 ...
- 对象的序列化与反序列化---IO学习笔记(四)
对象的序列化,反序列化 对象的序列化: 就是将Object转换成byte序列 对象的反序列化: 将byte序列转换成Object 序列化流.反序列化流 序列化流(ObjectOutputStream) ...
随机推荐
- BZOJ 4260: Codechef REBXOR (trie树维护异或最大值)
题意 分析 将区间异或和转化为前缀异或和.那么[L,R][L,R][L,R]的异或和就等于presum[R] xor presum[L−1]presum[R]\ xor \ presum[L-1]pr ...
- mybatis注解大全
注解 目标 相对应的 XML 描述 @CacheNamespace 类 <cache> 为给定的命名空间 (比如类) 配置缓存. 属性:implemetation,eviction, fl ...
- MacOS使用zsh & oh-my-zsh
shell 俗称壳,c 语言编写的命令解析器程序,是用户使用 linux 的桥梁. 目前常用的 Linux 系统和 OS X 系统的默认 Shell 都是 bash. zsh 和 bash 相似,且 ...
- Leetcode部分题目整理(Javascript)
3.无重复字符的最长子串 /** * @param {string} s * @return {number} */ var lengthOfLongestSubstring = function(s ...
- demo(一) react-native-router-flux
react-native init AwesomeProject cd AwesomeProject 安装模块 npm i react-native-router-flux --save
- 51 Nod 1449 砝码称重
1449 砝码称重 题目来源: CodeForces 基准时间限制:1 秒 空间限制:131072 KB 分值: 40 难度:4级算法题 收藏 关注 现在有好多种砝码,他们的重量是 w0,w1, ...
- Linux创建删除文件和文件夹
要想删除和创建,需要有root权限 [xwg@bogon ~]$ su root密码:[root@bogon xwg]# cd /home/a 切换到目录a[root@bogon a]# t ...
- delphi将两个Strlist合并,求交集 (保留相同的)
Function StrList_Join(StrListA,StrListB:String):String; //将两个Strlist合并,求交集 (保留相同的) var SListA,SListB ...
- Java的消息机制
Java消息机制 1.问: 什么是 Java 消息服务?答: Java 消息服务(Java Message Service,JMS) API 是一个用于访问企业消息传递系统的 API.是 Java 2 ...
- Maven项目导出jar包,包含依赖
1. Maven项目导出jar包,包含依赖:mvn dependency:copy-dependencies package 2. 可以在Project创建lib文件夹,输入以下命令:mvn depe ...