扎克非伯格


You dream don't work unless you do.


如何使用Gson的排除策略?

Gson是google解析Json的一个开源框架,同类的框架fastJson,JackJson等等,它的吊我就不赘述了。

假设我们现在有这么一个使用场景:有一个实体类,但并不是每个字段都想序列化到json中。

1
2
3
4
5
6
7
8
9
public class User {
private String name;
private int age;
private double high;
private double weight;
private String father;
...省略getter和setter
}

@Expose注解

有人会说很简单啊,只要把想序列化的字段前加上@Expose注解,这个是Gson自带的,用起来确实很方便。

1
2
3
Gson gson = new GsonBuilder()
.excludeFieldsWithoutExposeAnnotation()//只序列化和反序列化带Expose注解属性
.create();

然后按照以上方法构建出Gson实例,然后哔哩哔哩就完成了。excludeFieldsWithoutExposeAnnotation()一定要加上这个,不然不会生效。

当业务场景比较简单,以上方法确实简单、方便。但是当业务复杂起来,一个实体类里包含几十个字段也不是不可能,然后自由一个字段不想序列化的,这下真是日了狗了。@Expose复制粘贴几十遍,这样的代码显然是不优雅的,再极端一点,如果在上百上千个字段中排除一个,你肯定想砸键盘了。fastJson中有@JsonIgnore注解,可以方便的只排除一个,但是Gson里并没有类似的注解。
讲了这么多我们的主角该登场了。

@Exclus注解

1
2
3
4
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD})
public @interface Exclus {
}

我们先自定义一个注解Exclus,然后在想要排除的字段中加上,如下:

1
2
3
4
5
6
7
8
9
10
public class User {
private String name;
private int age;
private double high;
private double weight;
@Exclus
private String father;
...省略getter和setter
}

Gson本身是有提供ExclusionStrategy接口,就是让我们来自定义排除策略的,那我们就来实现它。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class MyExclusionStrategy implements ExclusionStrategy {
//需要跳过的字段
@Override
public boolean shouldSkipField(FieldAttributes f) {
return f.getAnnotation(Exclus.class) != null;
}
//如果需要跳过,也可以自定义
//@Target({ElementType.FIELD})改为@Target({ElementType.TYPE})其他都类似的
@Override
public boolean shouldSkipClass(Class<?> clazz) {
return false;
}
}

然后再把这家伙set到我们的Gson中,我们就可以发车了。

1
2
3
Gson gson = new GsonBuilder()
.setExclusionStrategies(new MyExclusionStrategy())
.create();

PS:其实给字段加上transient关键字也可以实现,但是我实际业务中是在本地序列化的时候是希望序列化这个字段的,在网络上传输时又是不希望的,所以只能用上面的方法。