Java 中 Gson的使用

JSON 是一種文本形式的數據交換格式,它比XML更輕量、比二進制容易閱讀和編寫,調式也更加方便;解析和生成的方式不少,Java中最經常使用的類庫有:JSON-Java、Gson、Jackson、FastJson等html

1、Gson的基本用法json

  Gson提供了fromJson() 和toJson() 兩個直接用於解析和生成的方法,前者實現反序列化,後者實現了序列化;同時每一個方法都提供了重載方法api

  (1)基本數據類型的解析數組

Gson gson = new Gson();
int i = gson.fromJson("100", int.class); //100
double d = gson.fromJson("\"99.99\"", double.class);  //99.99
boolean b = gson.fromJson("true", boolean.class);     // true
String str = gson.fromJson("String", String.class);   // String

  (2)基本數據類型的生成 ui

Gson gson = new Gson();
String jsonNumber = gson.toJson(100);       // 100
String jsonBoolean = gson.toJson(false);    // false
String jsonString = gson.toJson("String"); //"String"

  (3)POJO類的生成與解析google

public class User {
    //省略其它
    public String name;
    public int age;
    public String emailAddress;
}

  生成JSON: url

Gson gson = new Gson();
User user = new User("張三",24);
String jsonObject = gson.toJson(user); // {"name":"張三kidou","age":24}

  解析JSON: spa

Gson gson = new Gson();
String jsonString = "{\"name\":\"張三\",\"age\":24}";
User user = gson.fromJson(jsonString, User.class);

2、屬性重命名 @SerializedName 註解的使用.net

從上面POJO的生成與解析能夠看出json的字段和值是的名稱和類型是一一對應的,但也有必定容錯機制(如第一個例子第3行將字符串的99.99轉成double型),但有時候也會出現一些不和諧的狀況,如:設計

  指望的json格式:{"name":"張三","age":24,"emailAddress":"zhangsan@ceshi.com"}

  實際:{"name":"張三","age":24,"email_address":"zhangsan@ceshi.com"}

  Gson在序列化和反序列化時須要使用反射,通常各種庫都將註解放到annotations包下,打開源碼在com.google.gson包下有一個annotations,裏面有一個SerializedName的註解類。對於json中email_address這個屬性對應POJO的屬性則變成: 

@SerializedName("email_address")
public String emailAddress;

  爲POJO字段提供備選屬性名SerializedName註解提供了兩個屬性,上面用到了其中一個,別外還有一個屬性alternate,接收一個String數組

  注:alternate須要2.4版本

複製代碼
@SerializedName(value = "emailAddress", alternate = {"email", "email_address"})
public String emailAddress;
//當三個屬性(email_address、email、emailAddress)都中出現任意一個時都可以獲得正確的結果

//當多種狀況同時出時,以最後一個出現的值爲準。
Gson gson = new Gson();
String json = "{\"name\":\"張三kidou\",\"age\":24,\"emailAddress\":\"zhangsan@ceshi.com\",\"email\":\"zhangsan_2@ceshi.com\",\"email_address\":\"zhangsan_3@ceshi.com\"}";
User user = gson.fromJson(json, User.class);
System.out.println(user.emailAddress); // zhangsan_3@example.com
複製代碼

3、Gson中使用泛型

  例如:JSON字符串數組:["Android","Java","PHP"]

  當要經過Gson解析這個json時,通常有兩種方式:使用數組,使用List;而List對於增刪都是比較方便的,因此實際使用是仍是List比較多

  數組比較簡單:

Gson gson = new Gson();
String jsonArray = "[\"Android\",\"Java\",\"PHP\"]";
String[] strings = gson.fromJson(jsonArray, String[].class);

  對於List將上面的代碼中的 String[].class 直接改成 List<String>.class 是不行的,對於Java來講List<String> 和List<User> 這倆個的字節碼文件只一個那就是List.class,這是Java泛型使用時要注意的問題 泛型擦除

  爲了解決的上面的問題,Gson提供了TypeToken來實現對泛型的支持,因此將以上的數據解析爲List<String>時須要這樣寫

Gson gson = new Gson();
String jsonArray = "[\"Android\",\"Java\",\"PHP\"]";
String[] strings = gson.fromJson(jsonArray, String[].class);
List<String> stringList = gson.fromJson(jsonArray, new TypeToken<List<String>>() {}.getType());
//TypeToken的構造方法是protected修飾的,因此上面纔會寫成new TypeToken<List<String>>() {}.getType() 而不是 new TypeToken<List<String>>().getType()

  泛型解析對接口POJO的設計影響

    泛型的引入能夠減小無關的代碼:  

{"code":"0","message":"success","data":{}}
{"code":"0","message":"success","data":[]}

    咱們真正須要的data所包含的數據,而code只使用一次,message則幾乎不用,若是Gson不支持泛型或不知道Gson支持泛型的同窗必定會這麼定義POJO

public class UserResponse {
    public int code;
    public String message;
    public User data;
}

    當其它接口的時候又從新定義一個XXResponse將data的類型改爲XX,很明顯code,和message被重複定義了屢次,經過泛型能夠將code和message字段抽取到一個Result的類中,這樣只須要編寫data字段所對應的POJO便可:

public class Result<T> {
    public int code;
    public String message;
    public T data;
}  
//對於data字段是User時則能夠寫爲 Result<User> ,當是個列表的時候爲 Result<List<User>>

4、Gson的流式反序列化

  (1)自動方式

    Gson提供了fromJson()和toJson() 兩個直接用於解析和生成的方法,前者實現反序列化,後者實現了序列化。同時每一個方法都提供了重載方法  

Gson.toJson(Object);
Gson.fromJson(Reader,Class);
Gson.fromJson(String,Class);
Gson.fromJson(Reader,Type);
Gson.fromJson(String,Type);

  (2)手動方式:手動的方式就是使用stream包下的JsonReader類來手動實現反序列化,和Android中使用pull解析XML是比較相似的

複製代碼
String json = "{\"name\":\"張三\",\"age\":\"24\"}";
User user = new User();
JsonReader reader = new JsonReader(new StringReader(json));
reader.beginObject();
while (reader.hasNext()) {
    String s = reader.nextName();
    switch (s) {
        case "name":
        user.name = reader.nextString();
        break;
        case "age":
        user.age = reader.nextInt(); //自動轉換
        break;
        case "email":
        user.email = reader.nextString();
        break;
    }
}
reader.endObject(); // throws IOException
System.out.println(user.name);  //張三
System.out.println(user.age);   // 24
System.out.println(user.email); //zhangsan@ceshi.com                
複製代碼

  自動方式最終都是經過JsonReader來實現的,若是第一個參數是String類型,那麼Gson會建立一個StringReader轉換成流操做

  

5、Gson的流式序列化

  (1)自動方式

    

  Gson.toJson方法列表

  //PrintStream(System.out) 、StringBuilder、StringBuffer和*Writer都實現了Appendable接口。  

Gson gson = new Gson();
User user = new User("張三",24,"zhangsan@ceshi.com");
gson.toJson(user,System.out);

  (2)手動方式

複製代碼
JsonWriter writer = new JsonWriter(new OutputStreamWriter(System.out));
writer.beginObject() // throws IOException
    .name("name").value("張三")
     .name("age").value(24)
     .name("email").nullValue() //演示null
    .endObject(); // throws IOException
    writer.flush(); // throws IOException
//{"name":"張三","age":24,"email":null}
//除了beginObject、endObject還有beginArray和endArray,二者能夠相互嵌套,注意配對便可。beginArray後不能夠調用name方法,一樣beginObject後在調用value以前必需要調用name方法。
複製代碼

6、 使用GsonBuilder導出null值、格式化輸出、日期時間

  通常狀況下Gson類提供的 API已經能知足大部分的使用場景,但有時須要更多特殊、強大的功能時,這時候就引入一個新的類 GsonBuilder。

      GsonBuilder從名上也能知道是用於構建Gson實例的一個類,要想改變Gson默認的設置必須使用該類配置Gson

  GsonBuilder用法: 

//各類配置  //生成配置好的Gson
Gson gson = new GsonBuilder().create();

  (1)Gson在默認狀況下是不動導出值null的鍵的,如:

複製代碼
public class User {
     
     public String name;
     public int age;
   //省略
     public String email;

}
Gson gson = new Gson();
User user = new User(張三",24);
System.out.println(gson.toJson(user)); //{"name":"張三","age":24}
//email字段是沒有在json中出現的,當在調試時須要導出完整的json串時或API接中要求沒有值必須用Null時,就會比較有用。
複製代碼

  使用方法:

Gson gson = new GsonBuilder().serializeNulls() .create();
User user = new User("張三", 24);
System.out.println(gson.toJson(user)); //{"name":"張三","age":24,"email":null}

 

  格式化輸出、日期時間及其它:

複製代碼
Gson gson = new GsonBuilder()
    //序列化null
    .serializeNulls()
    // 設置日期時間格式,另有2個重載方法
    // 在序列化和反序化時均生效
    .setDateFormat("yyyy-MM-dd")
    // 禁此序列化內部類
     .disableInnerClassSerialization()
    //生成不可執行的Json(多了 )]}' 這4個字符)
    .generateNonExecutableJson()
     //禁止轉義html標籤
    .disableHtmlEscaping()
    //格式化輸出
    .setPrettyPrinting()
    .create();
//:內部類(Inner Class)和嵌套類(Nested Class)的區別        
相關文章
相關標籤/搜索