Gson的進(jìn)階使用

正確熟練的使用Gson這個開源庫能夠有效的提高開發(fā)的效率,它可以快捷的將json串轉(zhuǎn)化成Map<>,List<>或?qū)嶓w類,并支持反向操作

基本操作
// 序列化
String string = new Gson().toJson(user);
// 反序列化
User user = new Gson().fromeJson(string, User.class);
泛型的反序列化
// 序列化
String string = new Gson().toJson(userList);
// 反序列化
List<User> userList = new Gson().
    fromeJson(string, new TypeToken<List<User>>(){}.getType());

TypeToken的源碼,可以對Java的泛型有更深刻的理解

復(fù)雜嵌套json串需要注意的問題

有些json串的嵌套很復(fù)雜,對象中某個字段為列表,列表中又有多個對象。在處理這種json串的時候要注意的是,分步操作,每一步操作后打印json串看一下

// 錯誤的json串格式,沒有雙引號
[{rec_id=797, type=4, data=杭州, remark=}]

// 正確的json串格式是有雙引號的,這樣才能保證被正確的解析
[{"rec_id":"797","type":"4","data":"杭州","remark":""}]

// 實際上如果上面的remark字段不為空,這兩種都可以被解析
// 但一旦有字段為空,沒有雙引號的那種就會拋出異常

在提取json串中的某一個對象的時候,若想單獨(dú)轉(zhuǎn)換成一個json串,應(yīng)該使用下面的方式

Map map = gson.fromJson(json, Map.class);

// 這種寫法是錯誤的,轉(zhuǎn)換完會是上面那種錯誤的json格式
String newjson = map.get("data").toString();

// 這種轉(zhuǎn)換方式才是正確的,以為通過map取得的也是一個對象
// 需要反序列化一次才能得到j(luò)son串,而不是直接toString()
String newjson = gson.toJson(map.get("data"));
變量名的對應(yīng)

很多情況下Java中的成員變量是通過駝峰式命名的,例如userName,passWord。而json的串可能是通過數(shù)據(jù)庫生成,數(shù)據(jù)庫中字段的命名方式為user_name,pass_word。這兩種命名方式在某些開源框架中是可以實現(xiàn)相互轉(zhuǎn)換的,雖然Gson不支持自動轉(zhuǎn)換,但可以通過下面的方式來映射Java中的成員變量名和json串中的key

@SerializedName("user_name")
private String userName;
如果Java的成員變量沒有對應(yīng)的json串中的key,則這個變量會被賦值為null,所以在成員變量的類型定義的時候,應(yīng)避免使用基本數(shù)據(jù)類型,而使用對應(yīng)的包裝器類型去替代
控制變量是否序列化

和對應(yīng)變量名的方法差不多,也是通過注解的方式來控制的,一個是@Expose注解,還有一個是@Since注解

  • @Expose注解有兩個變量:serializedeserialize,默認(rèn)值都是true

    public class User {
          @Expose
          private String userName;
          @Expose(serialize = false)
          private int age;
          @Expose(serialize = false, deserialize = false)
          private boolean admin;
    }
    

    這時序列化只會輸出userName字段,反序列化只會給userName和age字段賦值
    需要注意的是,要想使@Expose這個注解生效,需要使用如下方法來構(gòu)建Gson對象

     Gson gson = new GsonBuilder()
                      .excludeFieldsWithoutExposeAnnotation().create();
    
  • @Since注解主要用于進(jìn)行版本的控制

    public class User {
         @Since(1.0)
         private String userName;
         @Since(1.1)
         private int age;
         @Since(1.1)
         private boolean admin;
    }
    
    Gson gson = new GsonBuilder().setVersion(1.0).create();
    

    在構(gòu)建Gson對象的時候使用GsonBuilder的方式,指定一個版本號,成員變量的版本號高于指定的版本號的時候,在轉(zhuǎn)換的時候?qū)缓雎?,例如上述例子,只有userName字段會被序列化和反序列化

重寫適配器

當(dāng)一個json串的字段的值為"",且這個字段對應(yīng)的成員變量的類型為int,由于空字符串無法轉(zhuǎn)化成int類型,所以就會報錯,這個時候多數(shù)情況下我們是希望其轉(zhuǎn)化成0的,或者是某一個默認(rèn)值,所以我們可以通過重寫適配器的方式,來達(dá)到我們想要達(dá)到的效果,僅以重寫int類型的適配器為例

public class IntegerDefaultAdapter 
        implements JsonSerializer<Integer>, JsonDeserializer<Integer> {
    @Override
    public Integer deserialize(JsonElement json, 
          Type typeOfT, JsonDeserializationContext context)
            throws JsonParseException {
        try {
            // 此處可自定義規(guī)則
            if (json.getAsString().equals("") || 
                json.getAsString().equals("null")) {
                return 0;
            }
        } catch (Exception ignore) {
            // catch error
        }
        try {
            return json.getAsInt();
        } catch (NumberFormatException e) {
            throw new JsonSyntaxException(e);
        }
    }

    @Override
    public JsonElement serialize(Integer src, Type typeOfSrc, 
          JsonSerializationContext context) {
        return new JsonPrimitive(src);
    }
}

// 構(gòu)造Gson對象的方式
Gson gson = new GsonBuilder()
      .registerTypeAdapter(Integer.class, new IntegerDefaultAdapter())
      .create();

如果要寫其他類型的適配器,只需要更改上面的Integer為對應(yīng)的類型即可

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容