这几天,由于项目的须要,接触了Google的Gson库,发现这个东西很好用,遂记下简单的笔记,供之后参考。至于Gson是干什么的,有什么优势,请各位同窗自行百度。html
拷贝到项目的lib文件夹中,并将其加入到buildPath中。使用maven的同窗,直接在pom中加入如下依赖便可:java
<dependency> <groupId>com.google.code.gson</groupId> <artifactId>gson</artifactId> <version>2.2.4</version> </dependency>
public class People { private String name; private int age; private boolean setName; //ignored setter and getter @Override public String toString() { return "name=" + name + " age=" + age + " setName=" + setName; } }
public class GsonTest { public static void main(String[] args) { People p = new People(); p.setAge(20); p.setName("People"); p.setSetName(true); Gson gson = new Gson(); System.out.println(gson.toJson(p)); } }
输出结果:json
{"name":"People","age":20,"setName":true}
以上只是Gson的简单实用,若是咱们须要将bool类型的属性setName在转换成json的时候不转换,怎么实现呢? maven
让字段不序列化的最简单的方式就是使用Java的关键字transient:ide
public class People { private String name; private transient int age;//age is a transient field private boolean setName; }
第3步测试类不变,则会有如下输出:svn
{"name":"People","setName":true}
此注解做用在属性上,代表当序列化和反序列化的时候,这个属性将会暴露给Gson对象。这个注解只有当建立Gson对象时使用GsonBuilder方式建立并调用了GsonBuilder.excludeFieldsWithoutExposeAnnotation() 方法的时候才有效,不然无效。下面是一个介绍@Expose注解如何使用的例子:测试
public class People { @Expose private String name; @Expose(serialize = false, deserialize = false) private int age; private boolean setName; }
若是你以new Gson()的方式建立Gson对象,toJson()方法和fromJson() 方法在序列化和反序列化的时候将会操做这4个属性。然而,若是你使用ui
Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create()
来建立Gson对象,Gson 的 toJson() 和 fromJson() 方法将会排除掉 setName 段,这是由于 setName 字段没有被注解 @Expose 所标记。 这个 Gson 对象一样会排除 age 字段,由于注解@Expose的属性 serialize 被设置成了 false。相似的,Gson也会在反序列化时排除掉 age 字段,由于 deserialize被设置成了 false。this
第3步测试类只改变Gson对象的建立过程,则会有如下输出:google
{"name":"People"}
先使用不一样的修饰符来修饰字段,
public class People { private String name; protected int age;//protected field private boolean setName; }
而后在构造GsonBuilder的时候,可使用如下方法,来过滤掉被指定修饰符修饰的字段:
Gson gson = new GsonBuilder().excludeFieldsWithModifiers(Modifier.PROTECTED).create();
输出:
{"name":"People","setName":true}
在Gson的包中找半天,还发现com.google.gson包下面有这么一个接口:ExclusionStrategy ,根据名字能够推断,这个接口是用来设置Gson转换的排除策略的,因而在官网http://google-gson.googlecode.com/svn/trunk/gson/docs/javadocs/index.html查了一下这个接口,发现只要实现这个接口,并将实现类的对象塞给Gson,在转换成json的时候,Gson就会过滤掉指定的类或者属性。因而有了下面的代码:
public class GsonTest { public static void main(String[] args) { People p = new People(); p.setAge(20); p.setName("People"); p.setSetName(true); ExclusionStrategy excludeStrategy = new SetterExclusionStrategy(); Gson gson1 = new GsonBuilder() .setExclusionStrategies(excludeStrategy) .create(); Gson gson2 = new Gson(); String json1 = gson1.toJson(p); String json2 = gson2.toJson(p); System.out.println(json1); System.out.println(json2); People p1 = gson1.fromJson(json1, People.class); People p2 = gson2.fromJson(json2, People.class); System.out.println(p1); System.out.println(p2); } private static class SetterExclusionStrategy implements ExclusionStrategy { public boolean shouldSkipClass(Class<?> clazz) { return false; } public boolean shouldSkipField(FieldAttributes f) { return f.getName().startsWith("set"); } } }
原来,Gson对象的建立有两种方式:new Gson()表示使用默认的配置建立一个Gson对象,而若是使用GsonBuilder.create()方法建立,则能够自定义一些设置,这主要是为了使建立的Gson更适合于某些特定的状况。上例中第一段蓝色的代码建立了一个Gson对象,这个对象拥有对以“set”字样开头的属性的过滤的配置(若是须要过滤掉某种类型,则重写ExclusionStrategy接口的shouldSkipClass(Class<?> clazz)方法便可,若是须要过滤掉多种状况,则能够多建立几个ExclusionStrategy的实现类对象,并在建立Gson对象的时候设置进去便可),所以在本例中,将People对象转换成Json的时候,属性setName将被过滤掉。因为json1中没有属性setName,因此将json1反序列化成People对象的时候,boolean类型的setName就没有了值,因此打印的时候取了boolean类型的默认值。因而有了如下结果:
{"name":"People","age":20} {"name":"People","age":20,"setName":true} name=People age=20 setName=false name=People age=20 setName=true
这个解决办法对方法的名称有要求,不是最佳解法。其实咱们也可使用自定义注解,这样的好处是不影响业务逻辑,也不影响方法命名。
首先定义一个自定义的注解Exclude:
import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) public @interface Exclude { }
接下来将这个注解标注在指定的字段上:
class People { private String name; @Exclude private int age; @Exclude private boolean setName; }
修改测试类,和ExclusionStrategy类:
public class GsonTest { public static void main(String[] args) { People p = new People(); p.setAge(20); p.setName("People"); p.setSetName(true); ExclusionStrategy excludeStrategy = new AnnotationExclusionStrategy(); Gson gson1 = new GsonBuilder().setExclusionStrategies(excludeStrategy) .create(); Gson gson2 = new Gson(); String json1 = gson1.toJson(p); String json2 = gson2.toJson(p); System.out.println(json1); System.out.println(json2); } private static class AnnotationExclusionStrategy implements ExclusionStrategy { public boolean shouldSkipClass(Class<?> clazz) { return false; } public boolean shouldSkipField(FieldAttributes f) { return f.getAnnotation(Exclude.class) != null; } } }
输出:
{"name":"People"} {"name":"People","age":20,"setName":true}
在com.google.gson.annotation包中,有几个注解Expose, SerializedName, Since和Until,他们各有各的做用,下面使用官方例子介绍经常使用的注解:
此注解做用在属性上,代表这个属性在序列化成Json的时候,须要将名字序列化成注解的value属性指定的值。
这个注解将会覆盖任何的FieldNamingPolicy, 包括默认的命名策略。下面是一个介绍@SerializedName注解如何使用的例子:
package com.my.gson; import com.google.gson.annotations.SerializedName; public class SomeClassWithFields { @SerializedName("name") private final String someField; private final String someOtherField; public SomeClassWithFields(String a, String b) { this.someField = a; this.someOtherField = b; } }
下面的代码展现了序列化上面这个测试类的结果:
SomeClassWithFields objectToSerialize = new SomeClassWithFields("a", "b"); Gson gson = new Gson(); String jsonRepresentation = gson.toJson(objectToSerialize); System.out.println(jsonRepresentation);
执行结果是:
{"name":"a","someOtherField":"b"}
因而可知,属性"someField"已经被序列化成了"name"。
注意:在@SerializedName的value中指定的属性名必须为有效的Json属性名。
参考地址:
https://howtoprogram.xyz/2016/10/16/ignore-or-exclude-field-in-gson