Google 的 Gson 庫,Gson 是一個很是強大的庫,能夠將 JSON 格式的數據轉化成 Java 對象,也支持將 Java 對象轉成 JSON 數據格式。web
本文將會快速開始使用 Gson 進行序列化操做。因爲不少讀者都是 Android 開發人員,咱們會提供 Java 環境中的 Gson。在開始以前,咱們須要引入 Gson 庫到本身的項目中,最新的版本是 2.8.0.json
compile 'com.google.code.gson:gson:2.8.0'
<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
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 屬性是用在反序列化上。
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 方法,無論是序列化仍是反序列化都會起做用,若是咱們只想其中一個起做用,選擇調下面的方法就好了:
用法和 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
Gson 內部使用的是 JsonReader 類,看源碼能發現裏面有一個 lenient 的屬性,默認是 false,也就是說默認值接受標準的 JSON 格式數據,若是數據有問題,將拋出異常解析失敗。
JsonReader 也提供了設置 lenient 屬性的方法,來忽略一些不標準的 JSON 數據格式。
特殊類型 Floats & Doubles
若是你 Java 對象中包含一個正常的 Floats 或者 Doubles 類型的數據,是能夠正常序列化獲得 JSON的,若是你傳入 Float.POSITIVE_INFINITY 值,Gson 將會拋出異常,由於這個值是不能符合 JSON 標準的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; }
只有是類的形式,咱們才能使用註解 @JsonAdapter 來添加 MerchantListSerializer。就像以前的一些註解用法同樣,並添加到你須要序列化的 Java model 中。
轉載自:做者:無名小子的雜貨鋪連接:https://www.jianshu.com/p/215708d00015來源:簡書簡書著做權歸做者全部,任何形式的轉載都請聯繫做者得到受權並註明出處。