Gson - 學習

 Google 的 Gson 庫,Gson 是一個很是強大的庫,能夠將 JSON 格式的數據轉化成 Java 對象,也支持將 Java 對象轉成 JSON 數據格式。web

Gson 依賴

本文將會快速開始使用 Gson 進行序列化操做。因爲不少讀者都是 Android 開發人員,咱們會提供 Java 環境中的 Gson。在開始以前,咱們須要引入 Gson 庫到本身的項目中,最新的版本是 2.8.0.json

Gradle 項目添加

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

Maven 項目添加

<dependencies> <dependency> <groupId>com.google.code.gson</groupId> <artifactId>gson</artifactId> <version>2.8.0</version> <scope>compile</scope> </dependency> </dependencies>

基礎
序列化:
UserSimple userObject = new UserSimple(
    "Norman",
    "norman@futurestud.io",
    26,
    true
);

Gson gson = new Gson();
String userJson = gson.toJson(userObject); 

反序列化:數組

String userJson = "{'age':26,'email':'norman@futurestud.io','isDeveloper':true,'name':'Norman'}";
Gson gson = new Gson();
UserSimple userObject = gson.fromJson(userJson, UserSimple.class);

 

數組反序列化:bash

public class Founder { String name; int flowerCount; }

String founderJson = "[{'name': 'Christian','flowerCount': 1}, {'name': 'Marcus', 'flowerCount': 3}, {'name': 'Norman', 'flowerCount': 2}]"; Gson gson = new Gson(); Founder[] founderArray = gson.fromJson(founderJson, Founder[].class);

 

列表List反序列化:數據結構

String founderJson = "[{'name': 'Christian','flowerCount': 1}, {'name': 'Marcus', 'flowerCount': 3}, {'name': 'Norman', 'flowerCount': 2}]";

Gson gson = new Gson();

Type founderListType = new TypeToken<ArrayList<Founder>>(){}.getType();

List<Founder> founderList = gson.fromJson(founderJson, founderListType);

 

列表做爲對象的一部分:反序列化時不須要傳遞 TypeTokenide

public class GeneralInfo {
    String name;
    String website;
    List<Founder> founders;
}


String generalInfoJson = "{'name': 'Future Studio Dev Team', 'website': 'https://futurestud.io', 'founders': [{'name': 'Christian', 'flowerCount': 1 }, {'name': 'Marcus','flowerCount': 3 }, {'name': 'Norman','flowerCount': 2 }]}";

Gson gson = new Gson();

GeneralInfo generalInfoObject = gson.fromJson(generalInfoJson, GeneralInfo.class);

 

Map反序列化:函數

public class AmountWithCurrency {
    String currency;
    int amount;
}

String dollarJson = "{ '1$': { 'amount': 1, 'currency': 'Dollar'}, '2$': { 'amount': 2, 'currency': 'Dollar'}, '3€': { 'amount': 3, 'currency': 'Euro'} }";

Gson gson = new Gson();

Type amountCurrencyType = new TypeToken<HashMap<String, AmountWithCurrency>>(){}.getType();

HashMap<String, AmountWithCurrency> amountCurrency =
gson.fromJson(dollarJson, amountCurrencyType);

Map 數據結構沒有根元素,如 "[",咱們就能夠像解析 List 那用解析嵌套的 Map。ui

 

Set反序列化this

String founderJson = "[{'name': 'Christian','flowerCount': 1}, {'name': 'Marcus', 'flowerCount': 3}, {'name': 'Norman', 'flowerCount': 2}]";

Gson gson = new Gson();

Type founderSetType = new TypeToken<HashSet<Founder>>(){}.getType();

HashSet<Founder> founderSet = gson.fromJson(founderJson, founderSetType);

 

泛型序列化:每種數據類型須要 new TypeToken 才能解析成功google

 

Gson gson = new Gson();

List<Integer> integerList = new ArrayList<>();  
integerList.add(1);  
integerList.add(2);  
integerList.add(3);

List<String> stringList = new ArrayList<>();  
stringList.add("1");  
stringList.add("2");  
stringList.add("3");

Type integerType = new TypeToken<List<Integer>>() {}.getType();  
Type stringType = new TypeToken<List<String>>() {}.getType();

String integerJson = gson.toJson(integerList, integerType);  
String stringJson = gson.toJson(stringList, stringType);

 

@SerializedName

@SerializedName 是另外一個很是實用的註解。@SerializedName 註解更改了自動匹配 JSON 字段的方式,平時開發中,咱們老是默認保持 Java 類屬性字段名和 JSON 的字段是一一對應,可有使用並非老是這樣的狀況,也許你沒有訪問繼承 Java 類或者你必須遵照公司的命名規則,這就須要使 @SerializedName 註解來匹配 Gson 字段,是一種很是優雅的方式。
public class UserSimple {     
      @SerializedName("fullName")   
      String name;    
      String email;  
      boolean isDeveloper;  
      int age;
  }
 @SerializedName(value = "fullName", alternate = "username")    
 private String name;  

SerializedName 接受兩個參數,value、alternate。

SerializedName 改變了默認序列化和默認反序列化的字段取值,序列化時就是 value 的名稱就是字段的名稱,alternate 屬性是用在反序列化上。

GsonBuider

public class UserNaming {
   String Name;
   String email_of_developer;
   boolean isDeveloper;
   int _ageOfDeveloper;
}

 

命名規則:

FieldNamingPolicy.IDENTITY:徹底匹配咱們 Java model 中的字段名,無論你有沒有設置其餘註解屬性

GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.setFieldNamingPolicy(FieldNamingPolicy.IDENTITY);
Gson gson = gsonBuilder.create();

UserNaming user = new UserNaming("Norman", "norman@futurestud.io", true, 26);
String usersJson = gson.toJson(user);

輸出:

{
    "Name": "Norman",
    "_ageOfDeveloper": 26,
    "email_of_developer": "norman@futurestud.io",
    "isDeveloper": true
}

FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES:將修改生成的 JSON 中的字段名,格式將所有變成小寫,而且每一個單詞用「_」 分割

{
    "name": "Norman",
    "_age_of_developer": 26,
    "email_of_developer": "norman@futurestud.io",
    "is_developer": true
}

FieldNamingPolicy.LOWER_CASE_WITH_DASHES:每一個單詞用「-」 分隔

FieldNamingPolicy.UPPER_CAMEL_CASE:規則是每一個單詞的第一個字母都要大寫,其餘不變

 {
    "Name": "Norman",
    "_AgeOfDeveloper": 26,
    "Email_of_developer": "norman@futurestud.io",
     "IsDeveloper": true
}

FieldNamingPolicy.UPPER_CAMEL_CASE_WITH_SPACES:每一個單詞的第一個字母會大寫、每一個單詞使用空格分隔、含有 「_」 的連接的不會在使用空格

{
    "Name": "Norman",
    "_Age Of Developer": 26,
    "Email_of_developer": "norman@futurestud.io",
    "Is Developer": true
}

 

FieldNamingStrategy 自定義規則

FieldNamingStrategy customPolicy = new FieldNamingStrategy() {
    @Override
        public String translateName(Field f) {
            return f.getName().replace("_", "");
      }
};

GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.setFieldNamingStrategy(customPolicy);
Gson gson = gsonBuilder.create();

UserNaming user = new UserNaming("Norman", "norman@futurestud.io", true, 26);
String usersJson = gson.toJson(user);

序列化null

GsonBuilder gsonBuilder = new GsonBuilder();  
gsonBuilder.serializeNulls(); //重點
Gson gson = gsonBuilder.create();

UserSimple user = new UserSimple("Norman", null, 26, true);  
String usersJson = gson.toJson(user);

 輸出:

{
      "age": 26,
      "email": null,
       "isDeveloper": true,
      "name": "Norman"
}

 

忽略策略

 ExclusionStrategies 將 Date 和 boolean 類型的字段忽略、shouldSkipField 是用來忽略單個字段的,若是你想要忽略帶有 「_」 的字段

GsonBuilder gsonBuilder = new GsonBuilder();  
gsonBuilder.setExclusionStrategies(new ExclusionStrategy() {  
    @Override
    public boolean shouldSkipField(FieldAttributes f) {
        return f.getName().contains("_");
    }

    @Override
    public boolean shouldSkipClass(Class<?> incomingClass) {
        return incomingClass == Date.class || incomingClass == boolean.class;
    }
});
Gson gson = gsonBuilder.create();

UserDate user = new UserDate("Norman", "norman@futurestud.io", 26, true);  
String usersJson = gson.toJson(user);

上面的例子使用的是 setExclusionStrategies 方法,無論是序列化仍是反序列化都會起做用,若是咱們只想其中一個起做用,選擇調下面的方法就好了:

  • addSerializationExclusionStrategy()
  • addDeserializationExclusionStrategy()

用法和 ExclusionStrategy 的實現同樣,可重寫兩個方法實現。

 

基於 Modifiers 的忽略規則:

public class UserModifier {  
    private String name;
    private transient String email;
    private static boolean isDeveloper;
    private final int age;
}

若是你想忽略 final 和 static 類型的字段, 保留 transient 類型的字段

GsonBuilder gsonBuilder = new GsonBuilder();  
gsonBuilder.excludeFieldsWithModifiers(Modifier.STATIC, Modifier.FINAL);  
Gson gson = gsonBuilder.create();

UserModifier user = new UserModifier("Norman", "norman@fs.io", 26, true);  
String usersJson = gson.toJson(user);

 

註解 @Expose

public class UserSimple {  
        @Expose()
        String name; // equals serialize & deserialize

        @Expose(serialize = false, deserialize = false)
        String email; // equals neither serialize nor deserialize

        @Expose(serialize = false)
        int age; // equals only deserialize

        @Expose(deserialize = false)
        boolean isDeveloper; // equals only serialize
}

根據 @Expose 的用法,UserSimple 序列化 JSON 輸出只有 name 和 isDeveloper,其餘連個字段就不會被輸出,由於 serialize 都是 false;

反序列化的話,只有 email 和 isDeveloper 被忽略,由於 deserialize = false


transient :使用 transient 來描述字段,將不能被序列化和反序列化
 
Lenient屬性:

Gson 內部使用的是 JsonReader 類,看源碼能發現裏面有一個 lenient 的屬性,默認是 false,也就是說默認值接受標準的 JSON 格式數據,若是數據有問題,將拋出異常解析失敗。

JsonReader 也提供了設置 lenient 屬性的方法,來忽略一些不標準的 JSON 數據格式。


特殊類型 Floats & Doubles

若是你 Java 對象中包含一個正常的 Floats 或者 Doubles 類型的數據,是能夠正常序列化獲得 JSON的,若是你傳入 Float.POSITIVE_INFINITY 值,Gson 將會拋出異常,由於這個值是不能符合 JSON 標準的
解決的辦法就是經過 GsonBuilder 設置 serializeSpecialFloatingPointValues() 方法
GsonBuilder gsonBuilder = new GsonBuilder();
    gsonBuilder.serializeSpecialFloatingPointValues();
    Gson gson = gsonBuilder.create();
    UserFloat userFloat = new UserFloat("Norman", Float.POSITIVE_INFINITY);
    String usersJson = gson.toJson(userFloat);
    System.out.println("userJson:" + usersJson);

 

自定義序列化:

public class UserSubscription {  
    String name;
    String email;
    int age;
    boolean isDeveloper;

    // new!
    List<Merchant> merchantList;
}

public class Merchant {  
    private int Id;
    private String name;

    // possibly more properties
}
JsonSerializer<Merchant> serializer = new JsonSerializer<Merchant>() {  
    @Override
    public JsonElement serialize(Merchant src, Type typeOfSrc, JsonSerializationContext context) {
        JsonObject jsonMerchant = new JsonObject();

        jsonMerchant.addProperty("Id", src.getId());

        return jsonMerchant;
    }
};

GsonBuilder gsonBuilder = new GsonBuilder();


gsonBuilder.registerTypeAdapter(Merchant.class, serializer);

Gson customGson = gsonBuilder.create();  
String customJSON = customGson.toJson(subscription);

 

自定義序列化List:

JsonSerializer<List<Merchant>> serializer =  
    new JsonSerializer<List<Merchant>>() {
        @Override
        public JsonElement serialize(List<Merchant> src, Type typeOfSrc, JsonSerializationContext context) {
            JsonObject jsonMerchant = new JsonObject();

            List<String> merchantIds = new ArrayList<>(src.size());
            for (Merchant merchant : src) {
                merchantIds.add("" + merchant.getId());
            }

            String merchantIdsAsString = TextUtils.join(",", merchantIds);

            jsonMerchant.addProperty("Ids", merchantIdsAsString);

            return jsonMerchant;
        }
}

GsonBuilder gsonBuilder = new GsonBuilder();

Type merchantListType = new TypeToken<List<Merchant>>() {}.getType();  

gsonBuilder.registerTypeAdapter(merchantListType, serializer);

Gson customGson = gsonBuilder.create();  
String customJSON = customGson.toJson(subscription);

//結果
{
  "age": 26,
  "email": "norman@fs.io",
  "isDeveloper": true,
  "merchantList": {
    "Ids": "23,42"
  },
  "name": "Norman"
}

 

簡化:

JsonSerializer<List<Merchant>> serializer =  
    new JsonSerializer<List<Merchant>>() {
        @Override
        public JsonElement serialize(List<Merchant> src, Type typeOfSrc, JsonSerializationContext context) {
            JsonArray jsonMerchant = new JsonArray();

            for (Merchant merchant : src) {
                jsonMerchant.add("" + merchant.getId());
            }

            return jsonMerchant;
        }
}
//結果
{
  "age": 26, "email": "norman@fs.io", "isDeveloper": true, "merchantList": [ "23", "42" ], "name": "Norman" }
 

 

自定義反序列化:

前三個表示年月日,是一個日期結構,後面四個字段表示一個 model 信息

//模型
public class UserDate {  
    private String name;
    private String email;
    private boolean isDeveloper;
    private int age;
    private Date registerDate;
}

//Json
"year": 116,
    "month": 5,
    "day": 21,
    "age": 26,
    "email": "norman@futurestud.io",
    "isDeveloper": true,
    "name": "Norman"
}

 

JsonDeserializer<UserDate> deserializer = new JsonDeserializer<UserDate>() {  
    @Override
    public UserDate deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
        JsonObject jsonObject = json.getAsJsonObject();

        Date date = new Date(
                jsonObject.get("year").getAsInt(),
                jsonObject.get("month").getAsInt(),
                jsonObject.get("day").getAsInt()
        );

        return new UserDate(
                jsonObject.get("name").getAsString(),
                jsonObject.get("email").getAsString(),
                jsonObject.get("isDeveloper").getAsBoolean(),
                jsonObject.get("age").getAsInt(),
                date
        );
    }
};

GsonBuilder gsonBuilder = new GsonBuilder();


gsonBuilder.registerTypeAdapter(UserDate.class, deserializer);

Gson customGson = gsonBuilder.create();  
UserDate customObject = customGson.fromJson(userJson, UserDate.class);

 

自定義對象示例建立:

//Json

 {
      "age": 26,
      "email": "norman@fs.io",
      "isDeveloper": true,
      "name": "Norman"
}

//Model
public class UserContext {  
    private String name;
    private String email;
    private boolean isDeveloper;
    private int age;

    // additional attribute, which is not part of the data model
    private Context context; 

    public UserContext(Context context) {
        this.context = context;
    }
}

若是你仍是用原來的方式來反序列化,那麼獲得的 Context 確定是null。你須要在映射以前的構造函數中來建立 Context,這是就須要用到 InstanceCreators。

String userSimpleJson = ...; // the JSON from the server, see above

GsonBuilder gsonBuilder = new GsonBuilder();  
gsonBuilder.registerTypeAdapter(  
    UserContext.class, 
    new UserContextInstanceCreator(getApplicationContext())
);
Gson customGson = gsonBuilder.create();

UserContext customObject = customGson.fromJson(userSimpleJson, UserContext.class);

private class UserContextInstanceCreator implements InstanceCreator<UserContext> {  
    private Context context;

    public UserContextInstanceCreator(Context context) {
        this.context = context;
    }

    @Override
    public UserContext createInstance(Type type) {
        // create new object with our additional property
        UserContext userContext = new UserContext(context);

        // return it to gson for further usage
        return userContext;
    }
}

 

@JsonAdapter 註解:

public class MerchantListSerializer implements JsonSerializer<List<Merchant>> {  
    @Override
    public JsonElement serialize(List<Merchant> src, Type typeOfSrc, JsonSerializationContext context) {
        JsonArray jsonMerchant = new JsonArray();

        for (Merchant merchant : src) {
            jsonMerchant.add("" + merchant.getId());
        }

        return jsonMerchant;
    }
}

public class UserSubscriptionAnnotation {  
    String name;
    String email;
    int age;
    boolean isDeveloper;

    // new!
    @JsonAdapter(MerchantListSerializer.class)
    List<Merchant> merchantList;
}

UserSubscriptionAnnotation subscription = new UserSubscriptionAnnotation( "Norman", "norman@fs.io", 26, true, subscribedMerchants);
Gson gson = new Gson();
String fullJSON = gson.toJson(subscription);
 

只有是類的形式,咱們才能使用註解 @JsonAdapter 來添加 MerchantListSerializer。就像以前的一些註解用法同樣,並添加到你須要序列化的 Java model 中。

能夠看到 merchantList 被添加了 @JsonAdapter(MerchantListSerializer.class) 註解,而 MerchantListSerializer 正是咱們序列化過程的實現類,這樣咱們就不用使用 GsonBuilder 它來建立的 Gson 對象,而是使用默認建立對象就能夠,也不須要那些複雜的設置。
 
反序列化:和序列化不一樣的是,@JsonAdapter(UserDateDeserializer.class) 註解是要添加在類級別上面,這是一點不一樣。
 

 

轉載自:做者:無名小子的雜貨鋪連接:https://www.jianshu.com/p/215708d00015來源:簡書簡書著做權歸做者全部,任何形式的轉載都請聯繫做者得到受權並註明出處。

相關文章
相關標籤/搜索