Android框架---Google官方Gson解析(上)
GitHub中的原始碼地址:https://github.com/google/gson
AS在專案的app目錄下的buile.gradle新增gson依賴:(如果需要jar包,文末可以下載)
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()); } }
執行結果:
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);
}
}
執行結果:
接下來介紹抽象基類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());
}
}
執行結果:
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);
}
}
執行結果:
替換冗餘、難看的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);
}
}
執行結果:
註解作用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("==========================");
}
}
執行結果:
過濾註解: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);
}
}
執行結果:
@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);
}
}
執行結果:
@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);
}
}
執行結果:
@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);
}
}
執行結果:
版本控制註解: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);
}
}
執行結果:
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);
}
}
執行結果: