从一个Bug开始,重新认识一个强大的 Gson

栏目: 服务器 · 发布时间: 5年前

内容简介:www.cnblogs.com/mafly/p/gson.html从一个 Bug 说起

作者: Mafly,

www.cnblogs.com/mafly/p/gson.html

从一个 Bug 说起

不知道你们发现没有,你写完的程序无论当时怎么测试,过一段时间总会出 Bug 。再说一个每天都在发生的例子:在你写完一篇博客后,立即检查的话,总是查不出自己写的错别字。

据说这些都包含有一些大脑对当下事物处理的逻辑在里边,而且还有心理学因素在里边,我也不懂。反正现在就是程序出 Bug 了!出 Bug 了!!Bug !!!

事情是这样的,客户端请求服务器开放接口时,我们是以 JSON 字符串的形式返回的,这时候本来正常返回形式是这样:

{
   "name": "mafly",
   "age": "18",
   "sex": "男"
}

但这个名字叫Mafly的人他不想让你知道他是男是女。就没填性别,程序中默认赋值为 null了,JSON 序列化时就发生了意想不到的事儿。

重现一下那个 Bug

用于转换 Java 对象为 Json 字符串和把 Json 字符串转换为对象的 工具 类有很多,Gson、Jackson、FastJson等,我们用的是 Gson, 它是 Google 开发的,还据传说它的性能比较强大一些。嗯,对,我们用的就是这个。先看示例代码:

public static void main(String[] args) {
   
   HashMap<String, Object> map = new HashMap<String, Object>();
   map.put("name", "mafly");
   map.put("age", "18");
   map.put("sex", null);

   String jsonString = new Gson().toJson(map);
   System.err.println(jsonString);
}

你猜会输出上面那段我们预期的 Json 串吗?然而并不会。

从一个Bug开始,重新认识一个强大的 Gson

就是这个当 Sex=null时,用 Gson 的tojson方法会把 null 值忽略,从而序列化之后输出不包含这个属性值的 Json 串。其实我们的预期是输出 {"sex": ""} 或 {"sex": null}, 那怎么做呢?

通过搜索引擎发现,网上大概存在以下三种解决方案:

  • 调用 toJson(Object src, Type typeOfSrc, JsonWriter writer) 方法

  • 注册自定义 TypeAdapter

  • 设置 serializeNulls 属性值(推荐)

前两种方式我没测试,推荐第三种方式,简单方便,源码如下:

GsonBuilder gsonBuilder = new GsonBuilder();
String jsonString1 = gsonBuilder.serializeNulls().create().toJson(map);
System.err.println(jsonString1);

输出符合我们的需求了, {"sex": null},如图:

从一个Bug开始,重新认识一个强大的 Gson

简单转到源码看了看,除了这一个设置还有很多,真是太方便了。调用serializeNulls()后, Gson 设置 serializeNulls 属性值为 true,默认是false,源码:

public GsonBuilder serializeNulls() {
   this.serializeNulls = true;
   return this;
}

重新认识一下 Gson

我看了几行 Gson 的源码后,我发现它可配置及特性多的数不胜数,可以用@SerializedName注解给属性重命名,用@Expose注解标识属性不进行序列化,支持 Map 的 key 为复杂对象的形式,日期类型转化为特定格式,还有区分版本进行显示,这些在日常项目中都极常用到,只不过好像我们之前都是自己实现的。

我简单建立了一个 UserInfo 实体类,里边包含了username、age、sex这三个属性值。试着测试了一下其中一两个:

1. @Expose 想让谁输出谁输出 ,注解代码如图:

从一个Bug开始,重新认识一个强大的 Gson

设置excludeFieldsWithoutExposeAnnotation(),看下面第三行是输出:

从一个Bug开始,重新认识一个强大的 Gson

2. @SerializedName 想怎么显示怎么显示 ,注解代码如图:

从一个Bug开始,重新认识一个强大的 Gson

我想把age再 Json序列化时显示maflyAge,现在就可以了,输出如下图:

从一个Bug开始,重新认识一个强大的 Gson

3. @Since、@Until 不同版本不同数据 ,注解代码如图:

从一个Bug开始,重新认识一个强大的 Gson

这里要设置setVersion(3.2),@Since标注的在 3.2 版本或之后才会输出,@Until标注的只在 3.2 版本前才有。效果输出如下图:

从一个Bug开始,重新认识一个强大的 Gson

当然,还有好多特性呢,比如字段首字母大写阿、结果格式化阿等等,我这里抛个砖,剩下的有需要的可以试试。

总结一下

这是由于一个 Json 序列化输出后发现的小 Bug ,也可以说不能算 Bug ,因为是我们对于自己使用的工具类并不了解导致的,所以,去试着了解你使用的任何一个开源工具类或项目,对于遇到的问题可以很好的得到解决,从而也可以提升自己吧。

Java工程师成神之路系列文章

在 GitHub 更新中 ,欢迎关注,欢迎star。

直面Java第241期:什么是计算机内存模型?解决了什么问题?

成神之路第015期:设计模式:单例模式

深入并发第008期:到底什么是计算机内存模型?

- MORE | 更多精彩文章 -

如果你喜欢本文,

请长按二维码,关注   Hollis.

转发至 朋友圈 ,是对我最大的支持。


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

复杂网络理论及其应用

复杂网络理论及其应用

汪小帆、李翔、陈关荣 / 清华大学出版社 / 2006 / 45.00元

国内首部复杂网络专著 【图书目录】 第1章 引论 1.1 引言 1.2 复杂网络研究简史 1.3 基本概念 1.4 本书内容简介 参考文献 第2章 网络拓扑基本模型及其性质 2.1 引言 2.2 规则网络 2.3 随机图 2.4 小世界网络模型 2.5 无标度网络模型 ......一起来看看 《复杂网络理论及其应用》 这本书的介绍吧!

JS 压缩/解压工具
JS 压缩/解压工具

在线压缩/解压 JS 代码

Base64 编码/解码
Base64 编码/解码

Base64 编码/解码

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具