参考链接:
1. https://www.jianshu.com/p/e740196225a4
2. https://www.jianshu.com/p/d62c2be60617
Gson的基本使用
Gson提供了fromJson() 和toJson() 两个直接用于解析和生成的方法,前者实现反序列化,后者实现了序列化。
POJO类的生成与解析
//JSON串1
{
"code": "0",
"msg": "操作成功",
"data": {
"name": "arsenal",
"age": 21,
"sex": "男",
}
}
要解析上面的Json串,我们需要定义下面两个类:
public class Person {
private String name;
private int age;
private String sex;
//省略了getter\setter 方法
}
public class Payload {
private String code;
private String msg;
private Person data;
//省略了getter\setter 方法
}
解析JSON:
Gson gson = new Gson();
String jsonString = "{
\"code\": \"0\",
\"msg\": \"操作成功\",
\"data\": {
\"name\": \"arsenal\",
\"age\": 21,
\"sex\": \"男\",
}
}";
Payload payload = gson.fromJson(jsonString, Payload.class);
生成JSON:
Payload payload = new Payload();
payload.setCode("0");
...
String jsonStr = gson.toJson(payload);
Gson中使用泛型
对于在Java中使用泛型,存在泛型擦除的问题,即对于Java来说List<String>
和List<User>
这俩个的字节码文件只一个那就是List.class
对于下面的JSON:
//JSON串2
{
"code": "0",
"msg": "操作成功",
"data": [
{
"name": "arsenal",
"age": 21,
"sex": "男",
},
{
"name": "stern",
"age": 22,
"sex": "男",
}
]
}
解析JSON串2,我们需要将Payload类修改为:
public class Payload<T> {
private String code;
private String msg;
private T data;
//省略了getter\setter 方法
}
则JSON串2对应的实体类为 Payload<List<Person>>
,此时就不能使用 Payload.class
来进行JSON串的解析了。为了解决的上面的问题,Gson为我们提供了TypeToken
来实现对泛型的支持:
Gson gson = new Gson();
String jsonArray = "{
\"code\": \"0\",
\"msg\": \"操作成功\",
\"data\": [
{
\"name\": \"arsenal\",
\"age\": 21,
\"sex\": \"男\",
},
{
\"name\": \"stern\",
\"age\": 22,
\"sex\": \"男\",
}
]
}";
List<String> stringList = gson.fromJson(jsonArray, new TypeToken<Payload<List<Person>>>() {}.getType());
//ps:TypeToken的构造方法是protected修饰的,所以上面才会写成new TypeToken<Payload<List<Person>>>() {}.getType() 而不是 new TypeToken<Payload<List<Person>>>().getType()
//百度“匿名内部类”
Gson 泛型使用的进一步封装
每次都需要根据具体类型来写new TypeToken<Payload<List<Person>>>() {}.getType()
,比较麻烦。下面我们将对Payload
类进行进一步封装。
Type
是Java中所有类型的父接口,在1.8以前是一个空接口,自1.8起多了个getTypeName()方法,下面有ParameterizedType、 GenericArrayType、 WildcardType、 TypeVariable 几个接口,以及Class类。
ParameterizedType 简单说来就是形如“ 类型<> ”的类型,如:Map< String,User >。下面就以 Map < String, User > 为例讲一下里面各个方法的作用。
public interface ParameterizedType extends Type {
// 返回Map<String,User>里的String和User,所以这里返回[String.class,User.clas]
Type[] getActualTypeArguments();
// Map<String,User>里的Map,所以返回值是Map.class
Type getRawType();
// 用于这个泛型上中包含了内部类的情况,一般返回null
Type getOwnerType();
}
有了上面的知识,我们可以把Payload
修改为:
public class Payload<T> {
private String code;
private String msg;
private T data;
//省略了getter\setter 方法
public static Payload fromJson(String json, Class clazz) {
Gson gson = new Gson();
Type listType = new ParameterizedType() {
public Type getRawType() {
return List.class;
}
public Type[] getActualTypeArguments() {
return new Type[]{clazz};
}
public Type getOwnerType() {
return null;
}
}
Type objectType = new ParameterizedType() {
public Type getRawType() {
return Payload.class;
}
public Type[] getActualTypeArguments() {
return new Type[]{listType};
}
public Type getOwnerType() {
return null;
}
}
return gson.fromJson(json, objectType);
}
}
这样,我们解析JSON串2,只需要:
Payload<List<Person>> result = Payload.fromJson(jsonStr2, Person);