重新认识一个强大的 Gson
从一个 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 串吗?然而并不会。
就是这个当 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}
,如图:
简单转到源码看了看,除了这一个设置还有很多,真是太方便了。调用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 想让谁输出谁输出,注解代码如图:
设置excludeFieldsWithoutExposeAnnotation()
,看下面第三行是输出:
2.@SerializedName 想怎么显示怎么显示,注解代码如图:
我想把age
再 Json序列化时显示maflyAge
,现在就可以了,输出如下图:
3.@Since、@Until 不同版本不同数据,注解代码如图:
这里要设置setVersion(3.2)
,@Since
标注的在 3.2 版本或之后才会输出,@Until
标注的只在 3.2 版本前才有。效果输出如下图:
当然,还有好多特性呢,比如字段首字母大写阿、结果格式化阿等等,我这里抛个砖,剩下的有需要的可以试试。
总结一下
这是由于一个 Json 序列化输出后发现的小 Bug ,也可以说不能算 Bug ,因为是我们对于自己使用的工具类并不了解导致的,所以,去试着了解你使用的任何一个开源工具类或项目,对于遇到的问题可以很好的得到解决,从而也可以提升自己吧。
我今天提出的这些都是 Gson 的小小特性,还有很多等待大家发现,期待一块交流成长。
重新认识一个强大的 Gson的更多相关文章
- 毕加索的艺术——Picasso,一个强大的Android图片下载缓存库,OkHttpUtils的使用,二次封装PicassoUtils实现微信精选
毕加索的艺术--Picasso,一个强大的Android图片下载缓存库,OkHttpUtils的使用,二次封装PicassoUtils实现微信精选 官网: http://square.github.i ...
- 一个强大的jquery分页插件
点击这里查看效果 这个分页插件使用方便,引用keleyidivpager.js和keleyidivpager.css文件,然后在htm(或者php,aspx,jsp等)页面中对分页总数,参数名,前缀后 ...
- Dubbo 泛化调用的参数解析问题及一个强大的参数解析工具 PojoUtils
排查了3个多小时,因为一个简单的错误,发现一个强大的参数解析工具,记录一下. 背景 Nodejs 通过 tether 调用 Java Dubbo 服务.请求类的某个参数对象 EsCondition 有 ...
- 一个强大的UI node 抽象
基于cocos2d -x的一个强大的 界面对象的基类 ---@type uinode ui 对象的抽象 --@usage -- 界面打开的执行流程 -- 带*的是可选重写的函数,不带*的为必须实现的 ...
- SpringMVC整合Shiro,Shiro是一个强大易用的Java安全框架,提供了认证、授权、加密和会话管理等功能
SpringMVC整合Shiro,Shiro是一个强大易用的Java安全框架,提供了认证.授权.加密和会话管理等功能. 第一步:配置web.xml <!-- 配置Shiro过滤器,先让Shiro ...
- Advanced Archive Password Recovery (ARCHPR) 是一个强大的压缩包密码破解工具,适用于ZIP和RAR档案的高度优化的口令恢复工具。
RAR压缩文件密码破解工具是一款简单易用的RAR文档和ZIP文档密码破解软件,如果你不小心忘了解压密码或是下载的RAR文件需要密码,那么均可以使用本软件进行暴力破解.不管WinRAR /RAR 的密码 ...
- bower一个强大的前端依赖包管理工具
在介绍之前,你必须的知道bower是基于nodejs开发的,所以你首先必须得有个nodejs环境,至于这么安装nodejs网上一大堆教程,对了使用bower还需要安装git,这里就不多说了. #### ...
- 分享一个强大的采集类,还可以模拟php多进程
做采集的时候,可以使用file_get_contents()去获取网页源代码,但是使用file_get_contents采集,速度慢,而且超时时间,不好控制.如果采集的页面不存在,需要等待的时间很长. ...
- direnv 一个强大的环境变量管理工具
direnv 是一个基于golang 编写的强大的环境变量管理工具,可以帮助我们简化环境变量管理,而且 支持的平台比较多. 基本使用 下载二进制软件包 https://github.com/dir ...
随机推荐
- 25、手把手教你Extjs5(二十五)Extjs5常用组件--form的基本用法
Extjs Form是一个比较常用的控件,主要用来显示和编辑数据的,今天这篇文章将介绍Extjs Form控件的详细用法,包括创建Form.添加子项.加载和更新数据.验证等. Form和Form Ba ...
- enum的java例子
Grade.java package com.zhiyuan.myenum; /** * <p>Title: 枚举类 * <p>Company: * @description ...
- PHPCMS快速建站系列之搜索功能
默认模板的搜索功能代码 <div class="bd"> <form action="{APP_PATH}index.php" method= ...
- Yii -- framework 目录结构说明
base 底层的类库文件 caching 所有缓存方法 cli 项目生成脚本 collecions 用PHP语言构造传统OO语言的数据存储单元.如队列,栈,哈希等等 console yii控制台 db ...
- SpringMVC常用注解@Controller,@Service,@repository,@Component
SpringMVC常用注解@Controller,@Service,@repository,@Component controller层使用@controller注解 @Controller 用于标记 ...
- sqlite3命令行
1.查看版本信息 sqlite3 -verion 2.创建/打开数据库 sqlite3 数据库名 例:sqlite3 test.db 如果test.db不存在就创建 如果存在,则打开3.退出 .q/. ...
- 新手如何学习java(java学习建议路线图)
怎么学习Java,这是很多新手经常会问我的问题,现在我简单描述下一个Java初学者到就业要学到的一些东西: 首先要明白Java体系设计到得三个方面:J2SE,J2EE,J2ME(KJAVA). ...
- jquery.cookie实战用法详细解析
Cookie是由服务器端生成,发送给User-Agent(一般是浏览器),浏览器会将Cookie的key/value保存到某个目录下的文本文件内,下次请求同一网站时就发送该Cookie给服务器(前提是 ...
- Java线程: 线程调度
线程调度是Java多线程的核心,只有好的调度,才能充分发挥系统的性能,提高程序的执行效率. 一.休眠 休眠的目的是使线程让出CPU的最简单做法,线程休眠的时候,会将CPU交给其他线程,以便轮换执行,休 ...
- PHP扩展之多线程
PHP一直以为不支持多线程,后面才知道有基于pThread的扩展包,地址如下: http://php.net/manual/zh/book.pthreads.php 我感兴趣的是以下几个点: 1.Th ...