Android框架---Google官方Gson解析(上)

时间:2022-09-15 12:58:36

Gson(又称Google Gson)是Google公司发布的一个开放源代码的Java库,主要用途为序列化Java对象为JSON字符串,或反序列化JSON字符串成Java对象。
JSON (JavaScript Object Notation) 是一种轻量级的数据交换格式,易于人阅读和编写,同时也易于机器解析和生成,广泛应用于各种数据的交互中,尤其是服务器与客户端的交互。

GitHub中的源码地址:https://github.com/google/gson

AS在项目的app目录下的buile.gradle添加gson依赖:(如果需要jar包,文末可以下载)

Android框架---Google官方Gson解析(上)


Gson的实例化方式:

Gson gson = new Gson();
//可以通过GsonBuilder配置多种选项
gson = new GsonBuilder()
.setLenient()// json宽松
.enableComplexMapKeySerialization()//支持Map的key为复杂对象的形式
.serializeNulls() //智能null
.setPrettyPrinting()// 调教格式
.disableHtmlEscaping() //默认是GSON把HTML 转义的
.create();

接下来介绍Gson的集中基本用法:

1、对象和json字符串的相互转换(先准备一个Person类)

public class Person {
private int per_id;
private String name;
private String sex;
private int age;

public Person(int per_id, String name, String sex, int age) {
this.per_id = per_id;
this.name = name;
this.sex = sex;
this.age = age;
}

//get、set和toString方法...
}

测试代码:

/**
* Created by Layne_Yao on 2017-9-28 上午10:46:43.
* CSDN:http://blog.csdn.net/Jsagacity
*/
public class GsonTest {

public static void main(String[] args) {
Gson gson = new Gson();
// 可以通过GsonBuilder配置多种选项
gson = new GsonBuilder()
.setLenient()// json宽松
.enableComplexMapKeySerialization()// 支持Map的key为复杂对象的形式
.serializeNulls() // 智能null
.setPrettyPrinting()// 调教格式
.disableHtmlEscaping() // 默认是GSON把HTML 转义的
.create();

Person person = new Person(10, "layne", "man", 18);
// 对象转换为json字符串
String str = gson.toJson(person);
System.out.println("对象转换为json字符串:" + str);

// json字符串转化为对象
Person person1 = gson.fromJson(str, Person.class);
System.out.println("json字符串转化为对象:" + person1.toString());

}

}

运行结果:

Android框架---Google官方Gson解析(上)


2、集合和json字符串之间的转换:

/**
* Created by Layne_Yao on 2017-9-28 上午11:03:21.
* CSDN:http://blog.csdn.net/Jsagacity
*/
public class CollectionTest {
public static void main(String[] args) {
Gson gson = new Gson();

// 1.1、List字符串集合转换为字符串
ArrayList<String> str_list = new ArrayList<>();
for (int i = 0; i < 5; i++) {
str_list.add("这是字符串" + i);
}
String json_str = gson.toJson(str_list);
System.out.println("这是list字符串集合转化为json:" + json_str);

// 1.2、这是json集合转化为list字符集合
Type type = new TypeToken<ArrayList<String>>() {
}.getType();
ArrayList<String> sList = gson.fromJson(json_str, type);
System.out.println("这是json集合转化为list字符集合:" + sList);
System.out.println("==========================================");


// 2.1、List对象集合转换为字符串
List<Person> list = new ArrayList<>();
for (int i = 0; i < 2; i++) {
Person person = new Person(i, "layne", "man", 18);
list.add(person);
}
String json_str1 = gson.toJson(list);
System.out.println("这是list对象集合转化为json:" + json_str1);

// 2.1、这是json转化为List对象集合
Type type1 = new TypeToken<ArrayList<Person>>() {
}.getType();
ArrayList<String> sList1 = gson.fromJson(json_str1, type1);
System.out.println("这是json转化为List对象集合:" + sList1);
System.out.println("==========================================");


//3.1、这是map集合转化为json
Map<String, Object> map = new HashMap<>();
map.put("per_id", 5);
map.put("name", "layne");
map.put("sex", "man");
map.put("age", "18");

String json_str2 = gson.toJson(map);
System.out.println("这是map集合转化为json:" + json_str2);

//3.2、从json字符串转化为map集合
Type type2 = new TypeToken<Map<String, Object>>() {
}.getType();
Map<String, Object> map1 = gson.fromJson(json_str2, type2);
System.out.println("这是json转化为map集合:" + map1);

}
}

运行结果: Android框架---Google官方Gson解析(上)


接下来介绍抽象基类JsonElement的继承体系类:

JSONObject、JSONArray和Android自带的差不多,参见上篇Android网络传输数据json解析的基本认识

JsonNull:实际上就是null的字符串字段

JsonPrimitive:这个其实挺有意思的,我们知道如果json转换成字符串会包含引号的转义,但是通过JsonPrimative我们可以获得为转义的字符串

/**
* Created by Layne_Yao on 2017-9-28 下午1:52:31.
* CSDN:http://blog.csdn.net/Jsagacity
*/
public class JsonTest {

public static void main(String[] args) {
// JsonNull jsonNull = new JsonNull();// 构造方法过时,推荐INSTANCE

JsonNull jsonNull = JsonNull.INSTANCE;
System.out.println("JsonNull:" + jsonNull);


Gson gson = new Gson();
Person person = new Person(1, "layne", "man", 18);
String json_str = gson.toJson(person);
System.out.println("json字符串:" + json_str);

JsonPrimitive jsonPrimitive = new JsonPrimitive(json_str);
System.out.println("JsonPrimitive字符串:" + jsonPrimitive);// 多了转义字符,以及头尾的双引号:"{\"per_id\":1,\"name\":\"layne\",\"sex\":\"man\",\"age\":18}"
System.out.println("JsonPrimitive字符串:" + jsonPrimitive.getAsString());
}
}

运行结果:

Android框架---Google官方Gson解析(上)


Gson库中的注解:有五种注解

Android框架---Google官方Gson解析(上)

首先着重的先说明重命名注解:SerializedName

注解的作用:转换key关键字,json转换成对象是,json字段的key默认必须和声明类的字段名称一样。但是如果服务器返回的数据中key是关键字,这该怎么办?例如key是case、switch等,我们在声明类的时候是不能用这些字段的。或许你会让服务端那边改动,那服务端可能要改动非常的大,但是实际情况是不太愿意去改的。而这时候重命名注解就派上用场了。
还有就是如果服务端返回的json的key太冗余、或是不直观,这是就可以简化一下,代码看起来比较的优雅。

替换关键字的key:

/**
* Created by Layne_Yao on 2017-9-28 下午4:08:23.
* CSDN:http://blog.csdn.net/Jsagacity
*/
public class AnnotationTest {
public class Person {
private int per_id;
private String name;
private String sex;
@SerializedName("case")
private int case_num;

public Person(int per_id, String name, String sex, int case_num) {
super();
this.per_id = per_id;
this.name = name;
this.sex = sex;
this.case_num = case_num;
}

@Override
public String toString() {
return "Person-->[per_id=" + per_id + ", name=" + name + ", sex="
+ sex + ", case_num=" + case_num + "]";
}

}

public static void main(String[] args) {
Gson gson = new Gson();
String json_str = "{\"per_id\":1,\"name\":\"layne\",\"sex\":\"man\",\"case\":18}";
Person person = gson.fromJson(json_str, Person.class);
System.out.println("服务端发送的情况:"+json_str);
System.out.println("移动端转换的情况:"+person);
}

}

运行结果:

Android框架---Google官方Gson解析(上)


替换冗余、难看的key:

/**
* Created by Layne_Yao on 2017-9-28 下午4:16:44.
* CSDN:http://blog.csdn.net/Jsagacity
*/
public class AnnotationTest1 {
public class Person {
private int per_id;
private String name;
private String sex;
@SerializedName("home_light_state")
private boolean state;

public Person(int per_id, String name, String sex, boolean state) {
super();
this.per_id = per_id;
this.name = name;
this.sex = sex;
this.state = state;
}

@Override
public String toString() {
return "Person [per_id=" + per_id + ", name=" + name + ", sex="
+ sex + ", state=" + state + "]";
}
}

public static void main(String[] args) {
Gson gson = new Gson();
String json_str = "{\"per_id\":1,\"name\":\"layne\",\"sex\":\"man\",\"home_light_state\":true}";
Person person = gson.fromJson(json_str, Person.class);
System.out.println("服务端发送的情况:"+json_str);
System.out.println("移动端转换的情况:"+person);
}

}

运行结果:

Android框架---Google官方Gson解析(上)


注解作用2:结合alternate 提供多种备用字段key来解析,@SerializedName(value = "state", alternate = { "plus", "all" })
如果json中有plus就会解析成state,如果有all也会解析成state,当然state依旧不变的。
注意1:value中的值不能出现在alternate中;
注意2:alternate的备选字段会后面的替换前面的。

实例代码:

/**
* Created by Layne_Yao on 2017-9-28 下午5:05:44.
* CSDN:http://blog.csdn.net/Jsagacity
*/
public class AnnotationTest2 {
public class Person {
private int per_id;
private String name;
private String sex;
@SerializedName(value = "state", alternate = { "plus", "all" })
private String state;

public Person(int per_id, String name, String sex, String state) {
super();
this.per_id = per_id;
this.name = name;
this.sex = sex;
this.state = state;
}

@Override
public String toString() {
return "Person [per_id=" + per_id + ", name=" + name + ", sex="
+ sex + ", state=" + state + "]";
}
}

public static void main(String[] args) {
Gson gson = new Gson();
String json_str = "{\"per_id\":1,\"name\":\"layne\",\"sex\":\"man\",\"all\":\"广东广州\"}";
Person person = gson.fromJson(json_str, Person.class);
System.out.println("服务端发送:"+json_str);
System.out.println("转换成:" + person);
System.out.println("==========================");

String json_str1 = "{\"per_id\":1,\"name\":\"layne\",\"sex\":\"man\",\"plus\":\"广东广州\"}";
Person person1 = gson.fromJson(json_str1, Person.class);
System.out.println("服务端发送:"+json_str1);
System.out.println("转换成:" + person1);
System.out.println("==========================");

//all在state之后,所以all会解析成state,值则是all的原先的值
String json_str2 = "{\"per_id\":1,\"name\":\"layne\",\"sex\":\"man\",\"state\":\"state广东广州\",\"all\":\"all广东广州\"}";
Person person2 = gson.fromJson(json_str2, Person.class);
System.out.println("服务端发送:"+json_str2);
System.out.println("转换成:" + person2);
System.out.println("==========================");

//state在最后,不用解析,解析后的值也是state原先的
String json_str3 = "{\"per_id\":1,\"name\":\"layne\",\"sex\":\"man\",\"plus\":\"plus广东广州\",\"state\":\"all广东广州\"}";
Person person3 = gson.fromJson(json_str3, Person.class);
System.out.println("服务端发送:"+json_str3);
System.out.println("转换成:" + person3);
System.out.println("==========================");
}

}

运行结果: Android框架---Google官方Gson解析(上)


过滤注解:Expose

源码:默认既可序列化又可反序列化

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Expose {

public boolean serialize() default true;

public boolean deserialize() default true;
}

可以排除不需要序列化的字段,需要配合GsonBuilder使用

Gson gson = new GsonBuilder()
.excludeFieldsWithoutExposeAnnotation()
.create();

不添加@Expose注解的字段将不会解析,分为以下几种情况:

1、不添加@Expose注解等同于@Expose(deserialize = false,serialize = false) 不做任何解析
2、@Expose(deserialize = true,serialize = false) 只解析用用,也就是反序列化可以,序列化不可以
3、@Expose(deserialize = false,serialize = true) 序列化可以,反序列化不行
4、@Expose(deserialize = true,serialize = true) 既可以序列化,也可以反序列化

实例代码:不添加@Expose注解等同于@Expose(deserialize = false,serialize = false) 不做任何解析

/**
* Created by Layne_Yao on 2017-9-29 上午9:29:08.
* CSDN:http://blog.csdn.net/Jsagacity
*/
public class ExposeTest {
public static class Person {
private int per_id;
private String name;
private String sex;
private boolean state;

public Person(int per_id, String name, String sex, boolean state) {
this.per_id = per_id;
this.name = name;
this.sex = sex;
this.state = state;
}

@Override
public String toString() {
return "Person-->[per_id=" + per_id + ", name=" + name + ", sex="
+ sex + ", state=" + state + "]";
}

}

public static void main(String[] args) {
String json_str = "{\"per_id\":1,\"name\":\"layne\",\"sex\":\"man\",\"state\":true}";
Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation()
.create();

Person person = gson.fromJson(json_str, Person.class);
System.out.println("反序列化:" + person);

Person person1 = new Person(2, "layne", "man", true);
String json_str1 = gson.toJson(person1);
System.out.println("序列化:"+json_str1);
}
}

运行结果:

Android框架---Google官方Gson解析(上)


@Expose(deserialize = true,serialize = false) 只解析用用,也就是反序列化可以,序列化不可以

/**
* Created by Layne_Yao on 2017-9-29 上午9:59:04.
* CSDN:http://blog.csdn.net/Jsagacity
*/
public class ExposeTest3 {
public static class Person {
@Expose(deserialize = true,serialize = false)
private int per_id;
@Expose(deserialize = true,serialize = false)
private String name;
@Expose(deserialize = true,serialize = false)
private String sex;
@Expose(deserialize = true,serialize = false)
private boolean state;

public Person(int per_id, String name, String sex, boolean state) {
this.per_id = per_id;
this.name = name;
this.sex = sex;
this.state = state;
}

@Override
public String toString() {
return "Person-->[per_id=" + per_id + ", name=" + name + ", sex="
+ sex + ", state=" + state + "]";
}

}
public static void main(String[] args) {
String json_str = "{\"per_id\":1,\"name\":\"layne\",\"sex\":\"man\",\"state\":true}";
Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation()
.create();

Person person = gson.fromJson(json_str, Person.class);
System.out.println("反序列化:" + person);

Person person1 = new Person(2, "layne", "man", true);
String json_str1 = gson.toJson(person1);
System.out.println("序列化:"+json_str1);
}
}

运行结果:

Android框架---Google官方Gson解析(上)


@Expose(deserialize = false,serialize = true) 序列化可以,反序列化不行

/**
* Created by Layne_Yao on 2017-9-29 上午9:56:57.
* CSDN:http://blog.csdn.net/Jsagacity
*/
public class ExposeTest2 {
public static class Person {
@Expose(deserialize = false,serialize = true)
private int per_id;
@Expose(deserialize = false,serialize = true)
private String name;
@Expose(deserialize = false,serialize = true)
private String sex;
@Expose(deserialize = false,serialize = true)
private boolean state;

public Person(int per_id, String name, String sex, boolean state) {
this.per_id = per_id;
this.name = name;
this.sex = sex;
this.state = state;
}

@Override
public String toString() {
return "Person-->[per_id=" + per_id + ", name=" + name + ", sex="
+ sex + ", state=" + state + "]";
}

}
public static void main(String[] args) {
String json_str = "{\"per_id\":1,\"name\":\"layne\",\"sex\":\"man\",\"state\":true}";
Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation()
.create();

Person person = gson.fromJson(json_str, Person.class);
System.out.println("反序列化:" + person);

Person person1 = new Person(2, "layne", "man", true);
String json_str1 = gson.toJson(person1);
System.out.println("序列化:"+json_str1);
}
}

运行结果:

Android框架---Google官方Gson解析(上)


@Expose(deserialize = true,serialize = true) 既可以序列化,也可以反序列化

/**
* Created by Layne_Yao on 2017-9-29 上午9:53:38.
* CSDN:http://blog.csdn.net/Jsagacity
*/
public class ExposeTest1 {
public static class Person {
@Expose //等同于 @Expose(deserialize = true,serialize = true)
private int per_id;
@Expose
private String name;
@Expose
private String sex;
@Expose
private boolean state;

public Person(int per_id, String name, String sex, boolean state) {
this.per_id = per_id;
this.name = name;
this.sex = sex;
this.state = state;
}

@Override
public String toString() {
return "Person-->[per_id=" + per_id + ", name=" + name + ", sex="
+ sex + ", state=" + state + "]";
}

}

public static void main(String[] args) {
String json_str = "{\"per_id\":1,\"name\":\"layne\",\"sex\":\"man\",\"state\":true}";
Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation()
.create();

Person person = gson.fromJson(json_str, Person.class);
System.out.println("反序列化:" + person);

Person person1 = new Person(2, "layne", "man", true);
String json_str1 = gson.toJson(person1);
System.out.println("序列化:"+json_str1);

}

}

运行结果:

Android框架---Google官方Gson解析(上)


版本控制注解:Since、Util

Since注解:Gson实例配置GsonBuilder.setVersion(n)使用,当n>=v时,才会序列化解析

实例代码:

/**
* Created by Layne_Yao on 2017-9-29 上午10:00:37.
* CSDN:http://blog.csdn.net/Jsagacity
*/
public class SinceTest {
public static class Person {
@Since(2)
private int per_id;
@Since(2)
private String name;
@Since(2)
private String sex;
@Since(2)
private boolean state;

public Person(int per_id, String name, String sex, boolean state) {
this.per_id = per_id;
this.name = name;
this.sex = sex;
this.state = state;
}

@Override
public String toString() {
return "Person-->[per_id=" + per_id + ", name=" + name + ", sex="
+ sex + ", state=" + state + "]";
}

}
public static void main(String[] args) {
String json_str = "{\"per_id\":1,\"name\":\"layne\",\"sex\":\"man\",\"state\":true}";
Gson gson = new GsonBuilder().setVersion(1)//版本为1
.create();

Person person = gson.fromJson(json_str, Person.class);
System.out.println("反序列化v=1:" + person);

Person person1 = new Person(2, "layne", "man", true);
String json_str1 = gson.toJson(person1);
System.out.println("序列化v=1:"+json_str1);
System.out.println("=================================");

Gson gson1 = new GsonBuilder().setVersion(2)//版本为2
.create();
Person person2 = gson1.fromJson(json_str, Person.class);
System.out.println("反序列化v=2:" + person2);

Person person3 = new Person(2, "layne", "man", true);
String json_str2 = gson1.toJson(person3);
System.out.println("序列化v=2:"+json_str2);
System.out.println("=================================");

Gson gson2 = new GsonBuilder().setVersion(3)//版本为3
.create();
Person person4 = gson2.fromJson(json_str, Person.class);
System.out.println("反序列化v=3:" + person4);

Person person5 = new Person(2, "layne", "man", true);
String json_str3 = gson2.toJson(person5);
System.out.println("序列化v=3:"+json_str3);
}

}

运行结果:

Android框架---Google官方Gson解析(上)


Util注解:Gson实例配置GsonBuilder.setVersion(n)使用,当n<v时,才会序列化解析

实例代码:

/**
* Created by Layne_Yao on 2017-9-29 上午10:17:54.
* CSDN:http://blog.csdn.net/Jsagacity
*/
public class UtilTest {
public static class Person {
@Until(2)
private int per_id;
@Until(2)
private String name;
@Until(2)
private String sex;
@Until(2)
private boolean state;

public Person(int per_id, String name, String sex, boolean state) {
this.per_id = per_id;
this.name = name;
this.sex = sex;
this.state = state;
}

@Override
public String toString() {
return "Person-->[per_id=" + per_id + ", name=" + name + ", sex="
+ sex + ", state=" + state + "]";
}
}

public static void main(String[] args) {
String json_str = "{\"per_id\":1,\"name\":\"layne\",\"sex\":\"man\",\"state\":true}";
Gson gson = new GsonBuilder().setVersion(1)// 版本为1
.create();

Person person = gson.fromJson(json_str, Person.class);
System.out.println("反序列化v=1:" + person);

Person person1 = new Person(2, "layne", "man", true);
String json_str1 = gson.toJson(person1);
System.out.println("序列化v=1:" + json_str1);
System.out.println("=================================");

Gson gson1 = new GsonBuilder().setVersion(2)// 版本为2
.create();
Person person2 = gson1.fromJson(json_str, Person.class);
System.out.println("反序列化v=2:" + person2);

Person person3 = new Person(2, "layne", "man", true);
String json_str2 = gson1.toJson(person3);
System.out.println("序列化v=2:" + json_str2);
System.out.println("=================================");

Gson gson2 = new GsonBuilder().setVersion(3)// 版本为3
.create();
Person person4 = gson2.fromJson(json_str, Person.class);
System.out.println("反序列化v=3:" + person4);

Person person5 = new Person(2, "layne", "man", true);
String json_str3 = gson2.toJson(person5);
System.out.println("序列化v=3:" + json_str3);

}

}

运行结果:

Android框架---Google官方Gson解析(上)

Gson2.7jar包下载