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) ...
随机推荐
- C# 数组(5) 持续更新
同一类型和不同类型的多个对象 使用同一类型的多个对象,使用集合和数组. 使用不同类型的多个对象,使用Tuple(元组). 初始化数组 ]; myArray 存放在栈中,而 myArray 的内容 放在 ...
- React生命周期, 兄弟组件之间通信
1.一个demo(https://www.reactjscn.com/docs/state-and-lifecycle.html) class Clock extends React.Componen ...
- luogu 4234 最小差值生成树 LCT
感觉码力严重下降~ #include <bits/stdc++.h> #define N 400006 #define inf 1000000000 #define setIO(s) fr ...
- TTTTTTTTTTTTTTTT hdu 5727 Necklace 阴阳珠 二分图匹配+暴力全排列
Necklace Time Limit: 3000/1500 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Su ...
- [Luogu] 宝藏
https://www.luogu.org/problemnew/show/P3959 模拟退火解法 发现prim求最小生成树是明显错误的 因为prim每次要取出边权最小的点 然而在这道T中这样做不一 ...
- MySQL 5.7半同步复制技术
一.复制架构衍生史 在谈这个特性之前,我们先来看看MySQL的复制架构衍生史. 在2000年,MySQL 3.23.15版本引入了Replication.Replication作为一种准实时同步方式, ...
- 前端导出pdf
html2canvas文档地址 http://html2canvas.hertzen.com/configuration 方式一:使用html2canvas和jspdf插件实现 该方式是通过html2 ...
- BZOJ 4898 Luogu P3778 [APIO2017]商旅 (分数规划、最短路)
题目链接: (bzoj)https://www.lydsy.com/JudgeOnline/problem.php?id=4898 (luogu)https://www.luogu.org/probl ...
- django快速实现完整登录系统,把登陆注册串在一起并增加cookie(六)
1.使用之前创建的项目和应用 mysite3 account 2.使用之前的数据库构造 class User(models.Model): username=models.CharField(max ...
- 16.合并两个排序的链表 Java
题目描述 输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则. 解题思路 两种解法:递归和非递归 参考代码 /* public class ListNode { ...