定义:Gson是Google提供用来java对象和Json数据之间进行映射的库,进行序列化/反序列化。
两个重要方法:
1.toJson():序列化
2.fromJson():反序列化
一共有两种序列化/反序列化类型,目录前三者属于第一种,后三者属于第二种。
1.一种是没用到泛型,不需要用到TypeToken类。
2.一种是用到泛型,反序列化的时候需要用到TypeToken类。
1)Java自定义类对象的序列化/反序列化
当我们java对象某个属性为null的时候(基础数据类型有默认值),那么序列化的时候不会Gson会忽略掉这个属性。但是集合以及数组的元素有null的时候,就不会忽略。
2)Java嵌套类对象的序列化/反序列化
当我们java对象某个属性为null的时候(基础数据类型有默认值),那么序列化的时候不会Gson会忽略掉这个属性。但是集合以及数组的元素有null的时候,就不会忽略。
class Person{ private String name; private int age; private String gender; private Doctor dt; public void setWorks(Doctor dt){ this.dt=dt; } } class Doctor{ private String workName; private int age; }
//实体类 Person p1=new Person("Tom",18,"boy"); //另一个实体类 Doctor dt=new Doctor("医生",33); //第二个实体类放入第一个实例类 p1.setWorks(dt); //实例化Gson对象 Gson gson=new Gson(); //序列化 String json=gson.toJson(p1); System.out.println(json); //反序列化 Person person2=gson.fromJson(json,Person.class) System.out.println(person2);
3)Array数组的序列化/反序列化
当我们java对象某个属性为null的时候(基础数据类型有默认值),那么序列化的时候不会Gson会忽略掉这个属性。但是集合以及数组的元素有null的时候,就不会忽略。如果数组元素里面有一个没有设置值,那么序列化的时候会设置为null,等到你反序列化的时候就显示为null。
//准备数据 Person[] person1=new Person[3]; person1[0]=new Person("Tom",18,"boy"); person1[1]=new Person("anaiy",13,"girl"); //实例化Gson对象 Gson gson=new Gson(); //序列化 String json=gson.toJson(person1); System.out.println(json); //反序列化,重点在于第二个参数 Person[] person2=gson.fromJson(json,Person[].class) System.out.println(person2[0]); System.out.println(person2[1]); System.out.println(person2[2]);
4)List的序列化/反序列化
因为Java的泛型只会在编译的时候存在,等到加载阶段泛型便没作用了,所以为了保存泛型,Gson库有个保存泛型的方法类,TypeToken类,好像用到了反射,不太懂。
如果不用TypeToken来反序列化,那么,从Json字符串读取出的List对象不知道放入哪个实体类中也就是不知道这Json的数据是属于哪个类的。
那么我们反序列化的时候想告诉我们的Gson,List集合里面泛型类型就是我们的XXX类怎么办?
new一个TypeToken,把完整的类型作为TypeToken的参数化类型也就是泛型指定到TypeToken里,然后加上花括号表示是一个匿名内部类,再.getType()获取Type类型。
//准备数据 List<Person> list1=new Arraylist<>(); list1.add(new Person("Tom",18,"boy")); list1.add(new Person("anyn",13,"girl")); list1.add(null); //实例化Gson对象 Gson gson=new Gson(); //序列化 String json=gson.toJson(list1); System.out.println(json); //反序列化 Type type=new TypeToken<List<Person>>(){}.getType(); List<Person> list2=gson.fromJson(json,type); System.out.println(list2.get(0)); System.out.println(list2.get(1)); System.out.println(list2.get(2));
5)Map的序列化/反序列化
和List集合类型对象在反序列化的时候和List一样,也需要TypeToken。
//设置client要传过去的虚拟数据 Map<String,Person> map1=new HashMap<>(); map1.put("1",new Person("Tom",18,"boy")); map1.put("2",new Person("anyn",13,"girl")); map1.put("3",null); map1.put(null,null); //实例化Gson对象 Gson gson=new Gson(); //序列化 String json=gson.toJson(map1); System.out.println(json); //server端传过来json数据,反序列化 Type type=new TypeToken<Map<String,Person>>(){}.getType(); Map<String,Person> map2=gson.fromJson(json,type); System.out.println(map2.get(null)); System.out.println(map2.get("1")); System.out.println(map2.get("3"));
6)Set的序列化/反序列化
和和List集合类型对象在反序列化的时候和List一样,也需要TypeToken。
如果是HashSet类型,则完全可以反序列化为List<>,因为序列化后的Json数据一致。
//准备数据 Set<Person> set1=new HashSet<>(); set1.add(new Person("Tom",18,"boy")); set1.add(new Person("anyn",13,"girl")); set1.add(null); //实例化Gson对象 Gson gson=new Gson(); //序列化 String json=gson.toJson(set1); System.out.println(json); //反序列化 Type type=new TypeToken<List<Person>>(){}.getType(); List<Person> set2=gson.fromJson(json,type); System.out.println(set2.get(0)); System.out.println(set2.get(1)); System.out.println(set2.get(2));
7)控制序列化/反序列化的变量名称
因为Gson序列化和反序列化的时候,都是参照着你的类里面的字段的变量名作为Json数据的Key。
但是如果!Json数据有个Key的名字刚好是Java里面的关键词(在Java里面关键词不能和变量名一样,会冲突报错)。
那么我们此时此刻就可以用到Gson为我们提供的一个注解叫做@SerializedName,来控制Json字段中Key的命名。
//无法以class作为字段名 @SerializedName("class") private int cla;
当我们用这个注解序列化的时候,数据会以注解名作为显示。
当我们用这个注解反序列化的时候,数据会以类的属性名作为显示。
8)控制变量是否参加序列化/反序列化
1.@Expose注解
1)加注解
此注解中有两个属性,一个是序列化serialize,一个是反序列化deserialize,都默认为true。
所以默认情况下加此注解和没加此注解没有什么区别。
当我们设置为false时,就代表不要序列化/反序列化此字段。
@Expose(serialize=false,deserialize=false) private int test1;
然后这样就可以了吗?
2)加方法
不,我们还需要在实例化Gson对象的时候,用Builder构建器调用excludeFieldsWithoutExposeAnnotation()方法,再创建create()。
@Expose(serialize=false,deserialize=false) private int test1;
2.transient关键字
属于Java里的关键字,和static等等同级,表示此属性不会参与任何的序列化和反序列化
private transient int test1;