fastjson:对于Exception中复杂类型(enum,...以及自定义类型)成员的处理

如果一个Exception类中有枚举类型或其他复杂类型(比如java.util.Date,或自定义类型)的成员,fastjson反序列化会抛出异常。

    // ServiceSecurityException 类型中 type 成员是个枚举类型SecurityExceptionType
    ServiceSecurityException exp = new ServiceSecurityException("hello").setType(SecurityExceptionType.INVALID_PERSON_ID).setDeviceID(10);
    // 序列化可以正常输出
    System.out.println(JSON.toJSONString(exp));
    // 反序列化就会抛出异常
    JSON.parseObject(JSON.toJSONString(exp), ServiceSecurityException.class);

抛出的异常如下:

com.alibaba.fastjson.JSONException: set property error, type at com.alibaba.fastjson.parser.deserializer.FieldDeserializer.setValue(FieldDeserializer.java:136) at com.alibaba.fastjson.parser.deserializer.ThrowableDeserializer.deserialze(ThrowableDeserializer.java:132) at com.alibaba.fastjson.parser.DefaultJSONParser.parseObject(DefaultJSONParser.java:626) at com.alibaba.fastjson.JSON.parseObject(JSON.java:348) at com.alibaba.fastjson.JSON.parseObject(JSON.java:252) at com.alibaba.fastjson.JSON.parseObject(JSON.java:471) at net.gdface.facelog.CloneTest.test(CloneTest.java:56)

这应该是个bug,(我用版本的是1.2.38,就是支持java7的最后一个版本,再往后的版本都是java8编译的).跟踪了fastjson的源码,发现用于Exception的反序列化的ThrowableDeserializer代码中对于自定义成员反序列化的逻辑处理过于简单,只考虑了简单数据类型。 看了最新版本1.2.41对应代码,发现这个bug在1.2.41已经解决了,但1.2.41是java8编译的,因为我的项目编译对java版本的要求是java7,所以不能使用。所以这个问题,还得自己想办法解决。

我解决方法是绕开它,因为是在ThrowableDeserializer这里的代码出了问题,所以不能让fastjson以ThrowableDeserializer来实现 序列化和反序列化。

步骤1–序列化过程

将异常类型中需要序列化的字段序列化成一个简单的json string,这样在反序列化时fastjson就不会把它当做一个异常类型交给ThrowableDeserializer来处理。

    public String toJsonString(ServiceSecurityException exp){
        HashMap<String,Object> fields = new HashMap<String,Object>();
        fields.put("type", exp.getType());
        fields.put("deviceID", exp.getDeviceID());
        return JSON.toJSONString(fields);
    }

步骤2–反序列化

JSON.parseObject方法将上一步的json string 反序列化成一个JSONObject对象,

步骤3–反序列化

TypeUtils.castToJavaBean将上一步的JSONObject对象转换为指定的异常类型

代码实现如下:

String jsonStr = toJsonString(exp);
JSONObject obj = JSON.parseObject(jsonStr);
ServiceSecurityException newExp = TypeUtils.castToJavaBean(obj, ServiceSecurityException.class);

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏java技术学习之道

Java IO详解

2193
来自专栏风中追风

写一个自己的springMVC

今天我们来实现一个简单的springMVC框架,可以理解为 springMVC1.0这个版本,只是功能比较简单而已;

35914
来自专栏编舟记

Java内部类的异常处理

最近遇到一个问题,使用Java写某个DSL标记语言X的parser(解析器)Maven插件的时候,对外暴露一个名为Callback的接口和一个待实现的方法get...

772
来自专栏微信公众号:Java团长

Java IO流学习总结

流是一组有顺序的,有起点和终点的字节集合,是对数据传输的总称或抽象。即数据在两设备间的传输称为流,流的本质是数据传输,根据数据传输特性将流抽象为各种类,方便更直...

1532
来自专栏difcareer的技术笔记

JNI实现源码分析【四 函数调用】正文0x01:dvmCallMethodV0x02:nativeFunc0x03: 何时赋值

有了前面的铺垫,终于可以说说虚拟机是如何调用JNI方法的了。JNI方法,对应Java中的native方法,所以我们跟踪对Native方法的处理即可。

964
来自专栏Kotlin源码阅读

kotlin源码阅读——字符串

filename:String.kt/StringsJVM.kt/Arrays.kt/CharSequence.kt

4164
来自专栏JadePeng的技术博客

JavaScript 实现接口 (Interfaces In JavaScript)

接口是面向对象编程里的重要特性,遗憾的是JavaScript并没有提供对接口的支持!怎么实现接口呢? 在实际中,我们可以在注释中定义好接口,在实际的代码中予以实...

4336
来自专栏Java编程

Java IO详解

初学Java时,一直搞不懂Java里面的io关系,在网上找了很多大多都是给个结构图草草描述也看的不是很懂。而且没有结合到java7 的最新技术,所以自己来整理一...

6710
来自专栏醒者呆

编程语言的基础——搞定JavaIO

关键字:IO基础,JUnit生命周期,字节流,字符流,字符编码,对象流,序列化,反序列化 Java I/O 流是一组有顺序的,有起点和终点的字节集合。是对设...

3995
来自专栏冷冷

【Jfinal源码】第一章 com.jfinal.core.JFinalFilter(1)

前言: 首先在gitosc获取到jfinal的源码,本学习笔记使用的是jfinal2.2版本。 ---- 从web.xml开始,我们去学习jfinal是怎么从...

2286

扫码关注云+社区

领取腾讯云代金券