2019独角兽企业重金招聘Python工程师标准>>>

本文为作者根据日常使用结合Gson源码注释及wiki所作的原创内容,转载请注明出处。

该系列其它文章

  • 你真的会用Gson吗?Gson使用指南(一)
  • 你真的会用Gson吗?Gson使用指南(二)
  • 你真的会用Gson吗?Gson使用指南(三)
  • 你真的会用Gson吗?Gson使用指南(四)

注:此系列基于Gson 2.4。

本次的主要内容:

  • 字段过滤的几种方法

    • 基于@Expose注解
    • 基于版本
    • 基于访问修饰符
    • 基于策略(作者最常用)
  • POJO与JSON的字段映射规则

一、字段过滤的几种方法

字段过滤Gson中比较常用的技巧,特别是在Android中,在处理业务逻辑时可能需要在设置的POJO中加入一些字段,但显然在序列化的过程中是不需要的,并且如果序列化还可能带来一个问题就是 循环引用 ,那么在用Gson序列化之前为不防止这样的事件情发生,你不得不作另外的处理。

以一个商品分类Category 为例。

{"id": 1,"name": "电脑","children": [{"id": 100,"name": "笔记本"},{"id": 101,"name": "台式机"}]
}

一个大分类,可以有很多小分类,那么显然我们在设计Category类时Category本身既可以是大分类,也可以是小分类。

public class Category {public int id;public String name;public List<Category> children;
}

但是为了处理业务,我们还需要在子分类中保存父分类,最终会变成下面的情况

public class Category {public int id;public String name;public List<Category> children;//因业务需要增加,但并不需要序列化public Category parent;
}

但是上面的parent字段是因业务需要增加的,那么在序列化是并不需要,所以在序列化时就必须将其排除,那么在Gson中如何排除符合条件的字段呢?下面提供4种方法,大家可根据需要自行选择合适的方式。

基于@Expose注解

@Expose提供了两个属性,且都有默认值,开发者可以根据需要设置不同的值。

@Expose

@Expose 注解从名字上就可以看出是暴露的意思,所以该注解是用于对处暴露字段的。可是我们以前用Gson的时候也没有@Expose 注解还是不正确的序列化为JSON了么?是的,所以该注解在使用new Gson() 时是不会发生作用。毕竟最常用的API要最简单,所以该注解必须和GsonBuilder配合使用。

使用方法: 简单说来就是需要导出的字段上加上@Expose 注解,不导出的字段不加。注意是不导出的不加

@Expose //
@Expose(deserialize = true,serialize = true) //序列化和反序列化都都生效
@Expose(deserialize = true,serialize = false) //反序列化时生效
@Expose(deserialize = false,serialize = true) //序列化时生效
@Expose(deserialize = false,serialize = false) // 和不写一样

注:根据上面的图片可以得出,所有值为true的属性都是可以不写的。

拿上面的例子来说就是

public class Category {@Expose public int id;@Expose public String name;@Expose public List<Category> children;//不需要序列化,所以不加 @Expose 注解,//等价于 @Expose(deserialize = false,serialize = false)public Category parent;
}

在使用Gson时也不能只是简单的new Gson()了。

Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create();
gson.toJson(category);

基于版本

Gson在对基于版本的字段导出提供了两个注解 @Since 和 @Until,和GsonBuilder.setVersion(Double)配合使用。@Since 和 @Until都接收一个Double值。

Since和Until注解

使用方法:当前版本(GsonBuilder中设置的版本) 大于等于Since的值时该字段导出,小于Until的值时该该字段导出。

class SinceUntilSample {@Since(4)public String since;@Until(5)public String until;
}public void sineUtilTest(double version){SinceUntilSample sinceUntilSample = new SinceUntilSample();sinceUntilSample.since = "since";sinceUntilSample.until = "until";Gson gson = new GsonBuilder().setVersion(version).create();System.out.println(gson.toJson(sinceUntilSample));
}
//当version <4时,结果:{"until":"until"}
//当version >=4 && version <5时,结果:{"since":"since","until":"until"}
//当version >=5时,结果:{"since":"since"}

注:当一个字段被同时注解时,需两者同时满足条件。

基于访问修饰符

什么是修饰符? publicstatic 、finalprivateprotected 这些就是,所以这种方式也是比较特殊的。
使用方式:

class ModifierSample {final String finalField = "final";static String staticField = "static";public String publicField = "public";protected String protectedField = "protected";String defaultField = "default";private String privateField = "private";
}

使用GsonBuilder.excludeFieldsWithModifiers构建gson,支持int形的可变参数,值由java.lang.reflect.Modifier提供,下面的程序排除了privateField 、 finalField 和staticField 三个字段。

ModifierSample modifierSample = new ModifierSample();
Gson gson = new GsonBuilder().excludeFieldsWithModifiers(Modifier.FINAL, Modifier.STATIC, Modifier.PRIVATE).create();
System.out.println(gson.toJson(modifierSample));
// 结果:{"publicField":"public","protectedField":"protected","defaultField":"default"}

到此为止,Gson提供的所有注解就还有一个@JsonAdapter没有介绍了,而@JsonAdapter将和TypeAdapter将作为该系列第4篇也是最后一篇文章的主要内容。

基于策略(自定义规则)

上面介绍的了3种排除字段的方法,说实话我除了@Expose以外,其它的都是只在Demo用上过,用得最多的就是马上要介绍的自定义规则,好处是功能强大、灵活,缺点是相比其它3种方法稍麻烦一点,但也仅仅只是想对其它3种稍麻烦一点而已。

基于策略是利用Gson提供的ExclusionStrategy接口,同样需要使用GsonBuilder,相关API 2个,分别是addSerializationExclusionStrategy 和addDeserializationExclusionStrategy 分别针对序列化和反序化时。这里以序列化为例。

例如:

Gson gson = new GsonBuilder().addSerializationExclusionStrategy(new ExclusionStrategy() {@Overridepublic boolean shouldSkipField(FieldAttributes f) {// 这里作判断,决定要不要排除该字段,return true为排除if ("finalField".equals(f.getName())) return true; //按字段名排除Expose expose = f.getAnnotation(Expose.class); if (expose != null && expose.deserialize() == false) return true; //按注解排除return false;}@Overridepublic boolean shouldSkipClass(Class<?> clazz) {// 直接排除某个类 ,return true为排除return (clazz == int.class || clazz == Integer.class);}}).create();

有没有很强大?

二、 POJO与JSON的字段映射规则

之前在你真的会用Gson吗?Gson使用指南(二) 属性重命名时 介绍了@SerializedName这个注解的使用,本节的内容与上一次差不多的,但既然叫映射规则那么说的自然是有规律的情况。
还是之前User的例子,已经去除所有注解:

User user = new User("怪盗kidou", 24);
user.emailAddress = "ikidou@example.com";

GsonBuilder提供了FieldNamingStrategy接口和setFieldNamingPolicysetFieldNamingStrategy两个方法。

默认实现
GsonBuilder.setFieldNamingPolicy 方法与Gson提供的另一个枚举类FieldNamingPolicy配合使用,该枚举类提供了5种实现方式分别为:

FieldNamingPolicy 结果(仅输出emailAddress字段)
IDENTITY {"emailAddress":"ikidou@example.com"}
LOWER_CASE_WITH_DASHES {"email-address":"ikidou@example.com"}
LOWER_CASE_WITH_UNDERSCORES {"email_address":"ikidou@example.com"}
UPPER_CAMEL_CASE {"EmailAddress":"ikidou@example.com"}
UPPER_CAMEL_CASE_WITH_SPACES {"Email Address":"ikidou@example.com"}

自定义实现
GsonBuilder.setFieldNamingStrategy 方法需要与Gson提供的FieldNamingStrategy接口配合使用,用于实现将POJO的字段与JSON的字段相对应。上面的FieldNamingPolicy实际上也实现了FieldNamingStrategy接口,也就是说FieldNamingPolicy也可以使用setFieldNamingStrategy方法。

用法:

Gson gson = new GsonBuilder().setFieldNamingStrategy(new FieldNamingStrategy() {@Overridepublic String translateName(Field f) {//实现自己的规则return null;}}).create();

注意: @SerializedName注解拥有最高优先级,在加有@SerializedName注解的字段上FieldNamingStrategy不生效!

本文完

下期预告(本系列最终篇):

  • 无所不能的TypeAdapter

转载于:https://my.oschina.net/anxiaole/blog/836745

你真的会用Gson吗?Gson使用指南(三)相关推荐

  1. gson java,Gson版本支持

    本篇文章帮大家学习Gson版本支持,包含了Gson版本支持使用方法.操作技巧.实例演示和注意事项,有一定的学习价值,大家可以用来参考. Gson提供了rollNo和name,稍后将其添加为一个新变量. ...

  2. 路由器android-267d3f,这才是真的高级货玩意:NETGEAR EX7700 AC2200三频无线Mesh扩展器使用体验...

    这才是真的高级货玩意:NETGEAR EX7700 AC2200三频无线Mesh扩展器使用体验 2019-04-14 15:15:08 60点赞 264收藏 116评论 朋友家里用的是NETGEAR( ...

  3. java gson fromjson,Gson的fromJson()方法

    Gson提供了fromJson()方法来实现从Json相关对象到java实体的方法. 在日常应用中,我们一般都会碰到两种情况,转成单一实体对象和转换成对象列表或者其他结构. 先来看第一种: 比如jso ...

  4. 你真的会给领导发微信吗?三发三不发,不懂这6招,必被敲打

    微信,已经成为最为普及的即时通讯工具.我们在生活和工作中,大量应用微信沟通.但是,你真的会给领导发微信吗?前不久,出了几件芝麻绿豆大的"糗事": 比如,某员工回复领导"嗯 ...

  5. 这回真的是挤时间了-PHP基础(三)

    hi 刚看了唐人街探案,5星好评啊亲.由于是早就约好的,也不好推辞(虽然是和男的..),但该写的还是得挤时间写.明天早上老师的项目结题,虽然和我关系不大,但不要添乱就好!! 1.PHP  一.PHP基 ...

  6. Gson:我爸是 Google

    点击上方蓝色"方志朋",选择"设为星标" 回复"666"获取独家整理的学习资料! 01.前世今生 我叫 Gson,是一款开源的 Java 库 ...

  7. 一起来开发Android的天气软件(四)——使用Gson解析数据

    离上一篇文章过去才4.5天,我们赶紧趁热打铁继续完成该系列的天气软件的开发.承接上一章的内容使用Volley实现网络的通信,返回给我们的是这一串Json数据{"weatherinfo&quo ...

  8. JSONObject 和 GSON 解析 JSON 数据详解(转)

    转载:http://www.jianshu.com/p/f99de3ec0636 点此进入:从零快速构建APP系列目录导图 点此进入:UI编程系列目录导图 点此进入:四大组件系列目录导图 点此进入:数 ...

  9. 废弃fastjson!大型项目迁移Gson保姆级实战

    前言 本篇文章是我这一个多月来帮助组内废弃fastjson框架的总结,我们将大部分Java仓库从fastjson迁移至了Gson. 这么做的主要的原因是公司受够了fastjson频繁的安全漏洞问题,每 ...

最新文章

  1. jbpm人工终止的开发
  2. 大白话5分钟带你走进人工智能-第十一节梯度下降之手动实现梯度下降和随机梯度下降的代码(6)...
  3. Oracle大象,大象工程(石头剪刀布PK游戏)
  4. 拍拍贷信贷申请审核竞赛模拟
  5. 解决Tomcat.exe或者startup.bat 一闪无法打开的问题
  6. Intel 5400平台 芯片组
  7. asp.net建立文件夹
  8. core api其他电脑不能访问接口_第 12 篇:加缓存为接口提速
  9. 爱与光 android4.0学习
  10. 对标阿里P6-P7高级Java程序员的进阶技术路线
  11. python 获取前几天的日期
  12. unity -- 泛型
  13. 三,java流程控制常见练习题及面试题
  14. opencv+mnist识别手写数字串
  15. WakeOnLAN下载
  16. php投影,使用 CSS 3 制作长投影
  17. 3dsmax2020安装教程
  18. python编写古诗_用Python实现古诗词填字游戏(一)
  19. JD6621快速充电协议芯片,带有PPS 控制器的USB-PD3.0
  20. 最全Python算法入门

热门文章

  1. ROS入门笔记(一): ROS简介
  2. python中不可变对象_Python中的可变对象与不可变对象、浅拷贝与深拷贝
  3. android判断是否已经安装成功,android 判断应用程序是否已安装
  4. mac json工具_工具类封装的思路 | 钉钉群机器人为例
  5. Java讲课笔记23:Map接口及其实现类
  6. SSM框架笔记12:Spring JdbcTemplate
  7. 【BZOJ3050】Seating,线段树
  8. mysql备库命令_mysql数据库备份命令
  9. bzoj1069 [SCOI2007]最大土地面积 凸包+单调性
  10. 【英语学习】【Level 07】U02 Live Work L2 A place to call my home