前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >发现Gson一个小Bug?

发现Gson一个小Bug?

作者头像
吴就业
发布2021-01-28 17:39:05
6630
发布2021-01-28 17:39:05
举报
文章被收录于专栏:Java艺术Java艺术

最近使用Gson序列化HashMap实例发现序列化结果为null。这其实不是什么Bug,后面我百度一下发现很多人都发现过这个问题,只是不知道出于什么考虑。

这是单元测试:

代码语言:javascript
复制
public class JsonTest {
    @Test
    public void testGsonMap() {
        Map<String, Object> data = new HashMap<String, Object>() {{
            put("xxx", "yyy");
        }};
        System.out.println(JsonUtils.toJsonString(data));
    }
}

一般情况下我们也不会这样使用,这是同事给我反馈的,一开始还以为是我封装的适配多json框架组件的Bug

其中JsonUtils#toJsonString方法实际调用的是Gson#toJson方法, 测试结果返回null。但切换到jackson框架是能够序列化成功的。

通过查看单元测试编译后的字节码发现“data”变量实际上是一个匿名类实例。这个匿名类继承HashMap,并且类名以$1结尾

经过调试后发现,Gson会过滤类名以$+数字结尾的匿名类实例,不会序列化此类型的实例。下面是调用栈:

代码语言:javascript
复制
com.google.gson.internal.Excluder#create
  >com.google.gson.internal.Excluder#excludeClassChecks
       >com.google.gson.internal.Excluder#isAnonymousOrLocal
            >java.lang.Class#isAnonymousClass

java.lang.Class#isAnonymousClass方法返回false时,这种类型的实例将不被序列化。

代码语言:javascript
复制
public final class Class<T> {
    public boolean isAnonymousClass() {
        return "".equals(getSimpleName());
    }
}

isAnonymousClass方法通过调用getSimpleName方法比较SimpleName是否是空串,然而getSimpleName方法会去掉类名的$符号以及跟随$符号后面的数字。

在此案例中,data变量的类型为com.xxx.JsonTest$1,去掉包名com.xxx,再去掉$符号之前的JsonTest后类名为$1,去掉$符号和后面的数字后,类名就是""

我试着在JsonTest里面写一个内部类com.xxx.JsonTest$Objcet2getSimpleName返回的是Objcet2。所以,Gson支持内部类,但不支持匿名内部类。

我也很难想到序列化使用匿名内部类的场景,但如果真的需要序列化匿名内部类,可以使用Gson.toJson(obj,type)方法。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2021-01-15,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Java艺术 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
文件存储
文件存储(Cloud File Storage,CFS)为您提供安全可靠、可扩展的共享文件存储服务。文件存储可与腾讯云服务器、容器服务、批量计算等服务搭配使用,为多个计算节点提供容量和性能可弹性扩展的高性能共享存储。腾讯云文件存储的管理界面简单、易使用,可实现对现有应用的无缝集成;按实际用量付费,为您节约成本,简化 IT 运维工作。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档