1. 程式人生 > >Gson之常見的序列化與反序列化

Gson之常見的序列化與反序列化

序列化與反序列化

在Gson的語境中序列化就是說把Java 物件轉化為Json字串,反序列化就是說把Json字串轉化為Java物件。

新增依賴

本篇部落格基於Gson 2.8.0版

compile 'com.google.code.gson:gson:2.8.0'

簡單Java物件

比如有一個學生類如下:

public class Student {
    public String name;
    public int age;
    public boolean isLOLPlayer;
}

序列化

Student stu=new Student("lin"
,18,true); //通過預設的方式 Gson gson=new Gson(); String stuJson=gson.toJson(stu);

輸出的Json字串如下

{"name":"lin","age":18,"isLOLPlayer":true}

反序列化

  //使用'是因為不想使用轉義字元\"
  String stuJosn="{'name':'lin','age':18,'isLOLPlayer':true}";
  Gson gson=new Gson();
  Student stu = gson.fromJson(stuJosn, Student.class);

通過打斷點檢視生成的物件如下:
這裡寫圖片描述

關於null值的處理
比如說name為null

 Student stu=new Student(null,18,true);

這時候預設情況下Gson會忽略掉這個欄位,不產生相關的資訊
輸出結果

{"age":18,"isLOLPlayer":true}

那麼反過來情況也是一樣的,假設json字元創中沒有name欄位,產生的java物件name屬性為null。這時候就要小心了,很可能會產生空指標異常

陣列/List/Set

我們知道Json中有陣列是以[ ]括起來的部分,Gson可以將它反序列化為Java中的陣列、List、Set,我們可以根據自己的實際需求來選擇。
如下學生有很多書:

public class Student {
    public String name;
    public int age;
    public boolean isLOLPlayer;
    public ArrayList<Book> books;
}

序列化:

 ArrayList<Book> books=new ArrayList<>();
 books.add(new Book("Thinking in Java","6666",78.0f));
 books.add(new Book("程式設計之美","8888",63f));
 Student stu=new Student("shilang",18,true,books);
 Gson gson=new Gson();
 String stuJosn=gson.toJson(stu);

輸出的Json如下:

{
    "age": 18,
    "books": [
        {
            "bookName": "Thinking in Java",
            "isbn": "6666",
            "price": 78.0
        },
        {
            "bookName": "程式設計之美",
            "isbn": "8888",
            "price": 63.0
        }
    ],
    "isLOLPlayer": true,
    "name": "shilang"
}

你會發現其實程式碼和上面的簡單Java物件沒什麼區別,確實如此,Gson內部幫我們處理了關於陣列的情況,所以反序列化的情況就不說了,因為這不是我要說的是重點。我們想說的是單獨一個數組或者List的情況,其實這時候序列化還是一樣的,只是反序列化有所不同。
比如把下面的Json反序列化:

[
    {
        "bookName": "Thinking in Java",
        "isbn": "6666",
        "price": 78.0
    },
    {
        "bookName": "程式設計之美",
        "isbn": "8888",
        "price": 63.0
    }
]

如果你使用陣列的話和之前的一樣:

 Book[] books = gson.fromJson(booksJson, Book[].class);

如果使用List的話,由於Java泛型擦除機制,執行時獲取不到型別,Gson設計一個TypeToken類解決這個問題,如下

 Type bookType=new TypeToken<ArrayList<Book>>(){}.getType();
 ArrayList<Book> books = gson.fromJson(booksJson, bookType);

這裡需要注意的是反序列化的Json陣列中的所有物件的型別必須一致,以便每一個都可以對映為同一個Java類。

使用Set

Type bookType=new TypeToken<Set<Book>>(){}.getType();
Set<Book> set=gson.fromJson(booksJson,bookType);

Map

仍然只說反序列化,比如下面一段Json

{
    "content": "This is Content",
    "title": "Hello",
    "url": "http://pngfi.github.io"
}

你可封裝成一個Java類,你也可以將其對映為Map,比如

Type mapType=new TypeToken<Map<String,String>>(){}.getType();
Map<String,String> map=gson.fromJson(mapJson,mapType);

不知道你有沒有注意到我並沒有具體指定哪種型別的Map,只是指定了型別為Map介面,這時候預設情況下Gson幫我們生成LinkedTreeMap 物件,這是Gson自己封裝的類。List在不指定具體型別時生成ArrayList,Set預設為LinkedHashSet
這裡寫圖片描述

Enum

比如說我定義了一個列舉Grade 表示學生成績等級,其中A,B,C,D為四個等級

public enum Grade {
    A,
    B,
    C,
    D
}

學生類程式碼如下:

public class Student {
    public Grade grade;
    public String name;
    public int age;
    public boolean isLOLPlayer;
}

這時候我們來序列化看一下結果:

 Student student=new Student(Grade.A,"shilang",15,false);
 Gson gson=new Gson();
 String stuJSON=gson.toJson(student);

結果如下:

{
    "age": 15,
    "grade": "A",
    "isLOLPlayer": false,
    "name": "shilang"
}

你會發現Gson幫我們將grade序列化為A

反序列化:
關於反序列化Gson肯定能將上面的那段Json反序列化為Java物件。

自定義列舉例項名:
這裡要說明一中額外情況,就是有可能你不想讓B序列化為字串B,而是想序列化為1,你就可以通過新增下面的註解來實現。

public enum Grade {
    A,
    @SerializedName("1") B,
    C,
    D
}

關於@SerializedName註解請看下篇博文