Gson
上一篇博客讲到了java的序列化,jdk自带的序列化有如下优缺点:
1、java序列化使用的方法都是jdk自带的,不需要引入第三方jar包即可使用。
2、java序列化生成的字节数组不能够跨平台使用,序列化之后的数据只能使用java语言进行反序列化,使用面窄。
3、java自带的序列化方式生成的数据占用空间比较大,同时序列化和反序列化的效率非常低。
那么其实,我们考虑使用序列化无非是想将对象转化成IO能够识别的数据,所以可以将对象转化为json格式或者xml格式的数据来进行传输或者存储,这篇博客我们就介绍一下常用的json化方式,java常用的json类库有:Gson、Fastjson、Jackson,笔者实际上常用的json类库是fastjson,但是由于fastjson最近爆出比较大的漏洞,在升级的同时也想学习一下其他的json化方式,所以本文介绍一下Gson的基本使用方法。
Gson基本使用方法
Gson提供了toJson()和fromJson()两种方法来提供序列化和反序列化的方法,同时提供了多种重载的方法。
首先定义一个Person类,供后面演示使用:
public class Person { private String name; private int age; private String sex; public Person(String name, int age, String sex) { this.name = name; this.age = age; this.sex = sex; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } @Override public String toString() { return "姓名为:"+name+"年龄为:"+age+"性别为:"+sex; } }
写一个最简单的程序,使用序列化和反序列化:
public class GsonDemo { public static void main(String[] args) { Gson gson =new Gson(); //定义一个Person类 Person person=new Person("张三",18,"男"); //序列化 String GsonObject=gson.toJson(person); //输出结果:{"name":"张三","age":18,"sex":"男"} System.out.println(GsonObject); //反序列化 Person person1=gson.fromJson("{\"name\":\"张三\",\"age\":18,\"sex\":\"男\"}",Person.class); //输出结果:姓名为:张三年龄为:18性别为:男 System.out.println(person1); } }
Gson别名的使用
Gson使用别名的方式主要是通过@SerializedName注解来实现,如下两种方式:
@SerializedName("person_name") private String name; @SerializedName(value = "person_age",alternate = {"age","ages"}) private int age;
在使用该注解并且里面只有单一的值时,则序列化和反序列化都使用注解内赋的值,而使用alternate,则在序列化的时候只会使用名字person_age而在反序列化的时候会识别person_age、age、ages三种名称的值,在已经序列化的数据只会识别出现在最后面的别名,执行程序如下:
public class GsonDemo { public static void main(String[] args) { Gson gson =new Gson(); //定义一个Person类 Person person=new Person("张三",18,"男"); //序列化 String GsonObject=gson.toJson(person); //输出结果:{"person_name":"张三","person_age":18,"sex":"男"} System.out.println(GsonObject); //反序列化,只会识别出现在最后面的age:17岁 Person person1=gson.fromJson("{\"person_name\":\"张三\",\"ages\":18,\"person_age\":16,\"age\":17,\"sex\":\"男\"}",Person.class); //输出结果:姓名为:张三年龄为:17性别为:男 System.out.println(person1); } }
Gson中处理属性NULL
在使用Gson序列化时,如果某个属性为null那么,序列化后的内容则不包含该属性,这个可能并不是我们想要的结果,虽然某个属性为空,但是我们序列化后还是要将其展示出来,某字段为空序列化如下:
public class GsonDemo { public static void main(String[] args) { Gson gson =new Gson(); //定义一个Person类 Person person=new Person("张三",18,null); //序列化 String GsonObject=gson.toJson(person); //输出结果:{{"person_name":"张三","person_age":18} System.out.println(GsonObject); } }
在Gson中有一个GsonBuilder工具可以处理序列化对象中属性为空的问题,同时也还可以固定时间属性的序列化格式如下:
public class GsonDemo { public static void main(String[] args) { Gson gson =new Gson(); //定义一个Person类 Person person=new Person("张三",18,null); //序列化,setDateFormat()只是为了展示固定日期格式而已 String GsonObject=new GsonBuilder().serializeNulls().setDateFormat("YYYY/MM/DD").create().toJson(person); //输出结果:{"person_name":"张三","person_age":18,"sex":null} System.out.println(GsonObject); //反序列化,只会识别出现在最后面的age:17岁 Person person1=new GsonBuilder().serializeNulls().setDateFormat("YYYY/MM/DD").create().fromJson("{\"person_name\":\"张三\",\"person_age\":18,\"sex\":null}",Person.class); //输出结果:姓名为:张三年龄为:18性别为:null System.out.println(person1); } }
Gson处理泛型
在Gson中如果对于Number、boolean、Object、String、Array则可以直接使用下面的方式即可
public class GsonDemo { public static void main(String[] args) { Gson gson=new Gson(); String StringObject="[\"Android\",\"Java\",\"PHP\"]"; String[] strings=gson.fromJson(StringObject,String[].class); /* 输出如下: Android ava PHP*/ for (String s:strings){ System.out.println(s); } } }
如果想使用List<String>.class则不行,所以Gson提供了new TypeToken<List<String>>(){}.getType()方式来提供支持泛型的序列化,而这种泛型的方式也经常用于web返回响应的场景,例如后端返回web端的一个请求{code:"0",message:"success",data{...}}。
public class RespData<T> { public int code; public String message; public T data; public int getCode() { return code; } public void setCode(int code) { this.code = code; } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } public T getData() { return data; } public void setData(T data) { this.data = data; } }
定义一个返回对结果类,由于后端返回的结果可能有各种不同的情况,所以使用泛型来表示后端返回的数据类型,返回结果数据就设置一个简单的String就可以了
public class RespDataObj { public String data; public String getData() { return data; } public void setData(String data) { this.data = data; } }
反序列化方法如下:
public class GsonDemo { public static void main(String[] args) { Gson gson=new Gson(); String StringObject="{\"code\":\"0\",\"message\":\"success\",\"data\":{\"data\": \"hello java\"}}"; RespData<RespDataObj> res=gson.fromJson(StringObject,new TypeToken<RespData<RespDataObj>>(){}.getType()); //输出结果 System.out.println(res.getData().getData()); } }