@html
Gson(又稱Google Gson)是Google公司發佈的一個開放源代碼的Java庫,主要用途爲序列化Java對象爲JSON字符串,或反序列化JSON字符串成Java對象。java
Gson官網:gson
Gson源碼地址:google/gsongit
使用Maven導入依賴:github
<dependency> <groupId>com.google.code.gson</groupId> <artifactId>gson</artifactId> <version>2.8.5</version> </dependency>
Gradle導入依賴:編程
compile group: 'com.google.code.gson', name: 'gson', version: '2.8.5'
使用Gson的第一步是建立一個Gson對象,建立愛你Gson對象有兩種方式:json
示例以下:數組
Gson gson = new Gson();
示例以下:網絡
GsonBuilder builder = new GsonBuilder(); Gson gson = builder.create();
下面會用到這個實體類:maven
public class Employee { private int id; private String firstName; private String lastName; private String email; //省略getter/setter,構造方法,toSting方法 }
在Gson中的序列化即將Java對象轉換爲其JSON表示形式。 爲了進行序列化,首先須要一個Gson對象,該對象能夠處理轉換。 接下來,須要調用函數toJson()方法並傳入Employee對象。ide
Employee emp = new Employee(1001, "Lokesh", "Gupta", "howtodoinjava@gmail.com"); Gson gson = new Gson(); String jsonString = gson.toJson(emp); System.out.println(jsonString);
運行結果:
在Gson進行反序列指的是將JSON字符串轉換爲Java對象。 爲了進行反序列化,咱們須要使用Gson對象調用fromJson()函數,並在解析完成後傳遞兩個參數,即JSON字符串和所需的Java類型。
String jsonString = "{'id':1001, 'firstName':'Lokesh', 'lastName':'Gupta', 'email':'howtodoinjava@gmail.com'}"; Gson gson = new Gson(); Employee empObject = gson.fromJson(jsonString, Employee.class); System.out.println(empObject);
運行結果:
默認狀況下,Gson以緊湊格式打印JSON,即字段名稱及其值,對象字段以及JSON輸出中數組內的對象等之間將沒有空格。
{"id":1,"firstName":"Lokesh","lastName":"Gupta", "emailId":"howtogoinjava@gmail.com"}
可是,這種緊湊的JSON可能很難閱讀。所以,GSON提供了一個漂亮的打印選項,能夠在其中打印JSON,以便於更加方便閱讀。
Gson gson = new GsonBuilder() .setPrettyPrinting() .create(); Employee employeeObj = new Employee(1, "Lokesh", "Gupta", "howtogoinjava@gmail.com"); System.out.println(gson.toJson(employeeObj));
運行結果:
users.json:
[ { "name": "Alex", "id": 1 }, { "name": "Brian", "id": 2 }, { "name": "Charles", "id": 3 } ]
User.java:
public class User { private long id; private String name; public long getId() { return id; } public void setId(long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "User [id=" + id + ", name=" + name + "]"; } }
將json數組反序列化爲Java對象數組:
String userJson = "[{'name': 'Alex','id': 1}, " + "{'name': 'Brian','id':2}, " + "{'name': 'Charles','id': 3}]"; Gson gson = new Gson(); User[] userArray = gson.fromJson(userJson, User[].class); for(User user : userArray) { System.out.println(user); }
運行結果:
將json數組反序列化爲根–到Java對象列表:
String userJson = "[{'name': 'Alex','id': 1}, " + "{'name': 'Brian','id':2}, " + "{'name': 'Charles','id': 3}]"; Gson gson = new Gson(); java.lang.reflect.Type userListType = new TypeToken<ArrayList<User>>() { }.getType(); ArrayList<User> userArray = gson.fromJson(userJson, userListType); for (User user : userArray) { System.out.println(user); }
運行結果:
若是Json數組是非根對象,則Gson能夠將JSON數組解析爲成員變量。咱們能夠按一般的方式使用fromJson()方法,將json數組解析爲所需的Java數組或列表。
department.json:
{ "id" : 1, "name" : "HR", "users" : [ { "name": "Alex", "id": 1 }, { "name": "Brian", "id": 2 }, { "name": "Charles", "id": 3 } ]
Department.java:
public class Department { private long id; private String name; private User[] users; //省略getter/setter、構造方法、toString方法 }
JsonArrayToMemberArray.java:
String departmentJson = "{'id' : 1, " + "'name': 'HR'," + "'users' : [" + "{'name': 'Alex','id': 1}, " + "{'name': 'Brian','id':2}, " + "{'name': 'Charles','id': 3}]}"; Gson gson = new Gson(); Department department = gson.fromJson(departmentJson, Department.class); System.out.println(department);
運行結果:
將json數組反序列化爲List類型成員變量。
Department2.java:
public class Department2 { private long id; private String name; private List<User> users; //省略getter/setter、構造方法、toString方法 }
轉換:
String departmentJson = "{'id' : 1, " + "'name': 'HR'," + "'users' : [" + "{'name': 'Alex','id': 1}, " + "{'name': 'Brian','id':2}, " + "{'name': 'Charles','id': 3}]}"; Gson gson = new Gson(); Department2 department = gson.fromJson(departmentJson, Department2.class); System.out.println(department);
運行結果:
使用Gson.toJson()方法將HashSet序列化爲JSON:
Set<String> userSet = new HashSet<String>(); userSet.add("Alex"); userSet.add("Brian"); userSet.add("Charles"); Gson gson = new Gson(); String jsonString= gson.toJson(userSet); System.out.println(jsonString);
運行結果:
使用Gson.fromJson()方法和TypeToken將JSON反序列化爲HashSet:
String jsonString = "['Alex','Brian','Charles','Alex']"; Gson gson = new Gson(); java.lang.reflect.Type setType = new TypeToken<HashSet<String>>(){}.getType(); Set<String> userSet = gson.fromJson(jsonString, setType); System.out.println(userSet);
運行結果:
Gson中實現的默認行爲是忽略空對象字段。
例如,若是在Employee對象中未指定電子郵件(即email爲null),則電子郵件將不會被序列化JSON輸出。Gson會忽略null字段,由於此行爲容許使用更緊湊的JSON輸出格式。
要配置Gson實例以輸出null,咱們必須使用GsonBuilder對象的serializeNulls()。
Gson gson = new GsonBuilder() .serializeNulls() .create();
應用程序隨着時間變化,模型類也隨之變化。有時候更新/刪除字段可能會被打斷。
全部這些更改均可以使用@Since註釋進行標記,以跟蹤模型類,在這些系統使用反序列化JSON數據進行交換時,與其餘系統的應用程序交互不會中斷。
在Gson中,可使用@Since註釋維護同一對象的多個版本。能夠在類,字段以及未來的方法中使用此註釋。它採用單個參數– ignoreVersionsAfter。
當咱們爲Gson實例配置版本號「 M.N」時,全部標記有版本大於M.N的類字段都將被忽略。例如,若是咱們將Gson配置爲版本號「 1.2」,則全部版本號更高的字段(例如1.三、1.4…)都將被忽略。
@Since(1.2) private String email;
在Employee類下面,咱們對三個字段進行了版本控制,即firstName,lastName和email。
public class Employee { private Integer id; @Since(1.0) private String firstName; @Since(1.1) private String lastName; @Since(1.2) private String email; }
要建立使用過@Since註解的Gson實例,須要使用GsonBuilder.setVersion()方法:
Gson gson = new GsonBuilder() .setVersion(1.1) .create();
讓序列號以上的Employee對象序列化。
Employee employeeObj = new Employee(1, "Lokesh", "Gupta", "howtogoinjava@gmail.com"); Gson gson = new GsonBuilder() .setVersion(1.1) .setPrettyPrinting() .create(); System.out.println(gson.toJson(employeeObj));
輸出:
{ "id": 1, "firstName": "Lokesh", "lastName": "Gupta" }
咱們將JSON字符串反序列化爲版本號爲Employee的對象。
String json = "{'id': 1001, " + "'firstName': 'Lokesh'," + "'lastName': 'Gupta'," + "'email': 'howtodoinjava@gmail.com'}"; Gson gson = new GsonBuilder() .setVersion(1.1) .setPrettyPrinting() .create(); Employee employeeObj = gson.fromJson(json, Employee.class); System.out.println(employeeObj);
輸出:
Employee [id=1001, firstName=Lokesh, lastName=Gupta, email=null]
在此Gson @SerializedName示例中,演示在序列化和反序列化過程當中更改json和java對象之間的字段名稱。
默認狀況下,咱們假設Java模型類和JSON將具備徹底相同的字段名稱。
但有時狀況並不是如此,某些名稱有所不一樣。如今咱們必須將json中的someName映射到Java類中的someOtherName。這是@SerializedName註解用到的地方。
@SerializedName註解指示帶註解的成員變量應使用提供的名稱值做爲其字段名稱序列化爲JSON。此註解將覆蓋可能一直在使用GsonBuilder類的任何FieldNamingPolicy,包括默認的字段命名策略。
請注意,在此註解中指定的值必須是有效的JSON字段名稱。
註解包含屬性
讓咱們以只有四個字段的Employee類爲例。咱們要建立一個JSON,其中「 email」被寫爲字段名「 emailId」:
public class Employee { private Integer id; private String firstName; private String lastName; @SerializedName(value = "emailId", alternate = "emailAddress") private String email; }
讓咱們序列化一個Employee實例並查看JSON輸出:
Employee emp = new Employee(1001, "Lokesh", "Gupta", "howtodoinjava@gmail.com"); Gson gson = new GsonBuilder().setPrettyPrinting().create(); System.out.println(gson.toJson(emp));
輸出:
{ "id": 1001, "firstName": "Lokesh", "lastName": "Gupta", "emailId": "howtodoinjava@gmail.com" }
在將JSON反序列化爲Java類的過程當中映射不一樣的字段名稱:
Json:
{ "id": 1001, "firstName": "Lokesh", "lastName": "Gupta", "email": "howtodoinjava@gmail.com", "emailAddress": "admin@gmail.com" }
Main.java:
String json = "{'id': 1001," + "'firstName': 'Lokesh'," + "'lastName': 'Gupta'," + "'email': 'howtodoinjava@gmail.com'," + "'emailAddress': 'admin@gmail.com'}"; Gson gson = new GsonBuilder().setPrettyPrinting().create(); Employee emp = gson.fromJson(json, Employee.class); System.out.println(emp);
輸出:
Employee [id=1001, firstName=Lokesh, lastName=Gupta, email=admin@gmail.com]
Gson容許咱們從Java類中排除或忽略不但願包含在序列化和反序列化中的字段。
Gson支持許多內置機制,用於排除頂級類,字段和字段類型。
GSON @Expose註解(com.google.gson.annotations.Expose)可用於標記對象序列化或反序列化時是否公開(包括活不包括)的字段。
@Expose註釋在要顯式指定應進行序列化或反序列化的全部字段的編程方式中頗有用。
@Expose是可選的,並提供兩個配置參數:
@Expose(serialize = false) private String lastName; @Expose (serialize = false, deserialize = false) private String emailAddress;
若是咱們使用 new Gson() 建立Gson並執行toJson() 和 fromJson() 方法,則@Expose將不會對序列化和反序列化產生任何影響。要使用此批註,咱們必須使用GsonBuilder類及其excludeFieldsWithoutExposeAnnotation()方法建立Gson實例。
Gson gson = new GsonBuilder() .excludeFieldsWithoutExposeAnnotation() .create();
默認狀況下,若是咱們僅將字段標記爲瞬時態,則Gson會將字段從序列化和反序列化中排除。
請記住,它沒法阻止單向轉換。它同時阻止了二者。
transient 具備與@Expose相同的效果(serialize = false,deserialize = false)。
@Expose(serialize = false) private String lastName; private transient String emailAddress;
經過使用GsonBuilder的excludeFieldsWithModifiers()方法,咱們能夠排除具備某些公共修飾符的字段。
例如,咱們要排除一個類的全部靜態成員,咱們能夠這樣建立Gson對象:
Gson gson = new GsonBuilder() .excludeFieldsWithModifiers(Modifier.STATIC) .create();
咱們可使用任意數量的Modifier常量來「 excludeFieldsWithModifiers」方法。例如:
Gson gson = new GsonBuilder() .excludeFieldsWithModifiers(Modifier.STATIC, Modifier.TRANSIENT, Modifier.VOLATILE) .create();
若是以上任何一種技術都不適合咱們,那麼咱們能夠建立本身的策略。
ExclusionStrategy用於肯定是否應將字段或頂級類做爲JSON輸出/輸入的一部分進行序列化或反序列化。
例如,在ExclusionStrategy定義下面,將排除全部使用@Hidden註釋註釋的字段:
//public @interface Hidden { // some implementation here //} // Excludes any field (or class) that is tagged with an "@Hidden" public class HiddenAnnotationExclusionStrategy implements ExclusionStrategy { public boolean shouldSkipClass(Class<?> clazz) { return clazz.getAnnotation(Hidden.class) != null; } public boolean shouldSkipField(FieldAttributes f) { return f.getAnnotation(Hidden.class) != null; } }
要使用此排除策略,在GsonBuilder對象中進行設置:
GsonBuilder builder = new GsonBuilder(); builder.setExclusionStrategies( new HiddenAnnotationExclusionStrategy() ); Gson gson = builder.create();
對於簡單的用例,使用'Gson gson = new Gson();' 標準配置就足夠了。 可是,若是打算自定義Gson的行爲,則可使用GsonBuilder自定義的配置來建立新的Gson實例。
GsonBuilder類提供一個.create()方法,該方法返回一個Gson實例。
Gson gson = new GsonBuilder().create();
默認狀況下,Gson將建立緊湊的JSON字符串。這對於減小經過網絡傳輸的數據量很是有用。
可是,這種緊湊的JSON對開發人員進行開發/調試應用程序時不友好。使用漂亮的打印來格式化JSON輸出:
Gson gson = new GsonBuilder() .setPrettyPrinting() .create();
FieldNamingPolicy枚舉在序列化期間爲JSON字段名稱提供了幾種標準命名約定。
它有助於Gson實例將Java字段名稱正確轉換爲所需的JSON字段名稱。
注意:如下任何命名約定均不會影響以@SerializedName註釋的字段。咱們將驗證使用User類的每一個策略生成的名稱。
User.java:
public class User { private int id; private String first_Name; private String lastName; private String _email; }
如何使用FieldNamingPolicy:
User user = new User(1, "Lokesh", "Gupta", "admin@howtodoinjava.com"); Gson gson = new GsonBuilder() .setFieldNamingPolicy(FieldNamingPolicy.IDENTITY) .setPrettyPrinting().create(); System.out.println(gson.toJson(user));
如下演示每種命名策略下轉換的不一樣的名稱。
使用此命名策略字段名稱不變。這個是默認的策略:
{ "id": 1, "first_Name": "Lokesh", "lastName": "Gupta", "_email": "admin@howtodoinjava.com" }
Gson會將Java字段名稱從其駝峯大小寫形式修改成小寫的字段名稱,其中每一個單詞都用破折號(-)分隔。
{ "id": 1, "first_-name": "Lokesh", "last-name": "Gupta", "_email": "admin@howtodoinjava.com" }
Gson會將Java字段名稱從其駝峯大小寫形式修改成小寫的字段名稱,其中每一個單詞都用點(.)分隔:
{ "id": 1, "first_.name": "Lokesh", "last.name": "Gupta", "_email": "admin@howtodoinjava.com" }
Gson會將Java字段名稱從其駝峯大小寫形式修改成小寫的字段名稱,其中每一個單詞都用下劃線(_)分隔。
{ "id": 1, "first__name": "Lokesh", "last_name": "Gupta", "_email": "admin@howtodoinjava.com" }
Gson將確保序列化爲JSON格式的Java字段名稱的第一個「字母」大寫:
{ "Id": 1, "First_Name": "Lokesh", "LastName": "Gupta", "_Email": "admin@howtodoinjava.com" }
Gson將確保在將Java字段名稱的第一個「字母」序列化爲JSON格式時將其大寫,而且單詞之間將使用空格分隔:
{ "Id": 1, "First_ Name": "Lokesh", "Last Name": "Gupta", "_Email": "admin@howtodoinjava.com" }
默認狀況下,Gson會在序列化過程當中忽略null值。可是,有時咱們想序列化具備空值的字段,以便它必須出如今JSON中。爲此,可使用serializeNulls()方法:
Employee employeeObj = new Employee(1, "Lokesh", "Gupta", null); Gson gson = new GsonBuilder() .serializeNulls() .setPrettyPrinting().create(); System.out.println(gson.toJson(employeeObj));
輸出:
{ "id": 1, "firstName": "Lokesh", "lastName": "Gupta", "emailId": null }
ExclusionStrategy用於肯定是否應將字段或頂級類做爲JSON輸出/輸入的一部分進行序列化或反序列化。
shouldSkipField(attribute)方法也是相同的規則。
在下面的示例中,使用@NPI註解和屬於Account類的實例的成員字段不會進行序列化和反序列化。
Gson gson = new GsonBuilder() .setExclusionStrategies(new ExclusionStrategy() { @Override public boolean shouldSkipField(FieldAttributes f) { return f.getAnnotation(NPI.class) != null; } @Override public boolean shouldSkipClass(Class<?> clazz) { return clazz.getAnnotation(Account.class) != null; } }) .setPrettyPrinting() .create();
在反序列化期間,Gson使用了一個寬鬆的JsonReader類。這意味着它僅接受兼容的JSON輸入。
若是JSON違反結構規則之一,它將拋出MalformedJsonException。若是咱們將lenient設置爲true,則它將忽視某些違規行爲,並嘗試讀取格式不正確的JSON。
Gson gson = new GsonBuilder() .setLenient() .setPrettyPrinting().create();
使用Gson JsonReader類,該類是基於拉式的流JSON解析器。它有助於將JSON做爲令牌流讀取。
在流模式下,每一個JSON數據都被視爲一個單獨的令牌。
當咱們使用JsonReader對其進行處理時,每一個令牌將被順序處理。例如,
{ "name":"Lokesh" }
在使用JsonReader進行解析時,以上JSON將生成4個令牌:
咱們可使用它的簡單構造函數建立一個JsonReader實例,該實例接受java.io.Reader類型的輸入流。
String json = "{}"; JsonReader jsonReader = new JsonReader( new StringReader(json) );
咱們能夠根據JSON流的來源使用如下閱讀器之一:
建立包含有效JSON源的JsonReader以後,咱們能夠開始遍歷流令牌並查看令牌值。
如下是使用JsonReader以令牌形式讀取簡單JSON的示例:
import java.io.IOException; import java.io.StringReader; import com.google.gson.stream.JsonReader; import com.google.gson.stream.JsonToken; public class Main { public static void main(String[] args) throws Exception { String json = "{'id': 1001,'firstName': 'Lokesh','lastName': 'Gupta','email': null}"; JsonReader jsonReader = new JsonReader(new StringReader(json)); jsonReader.setLenient(true); try { while (jsonReader.hasNext()) { JsonToken nextToken = jsonReader.peek(); if (JsonToken.BEGIN_OBJECT.equals(nextToken)) { jsonReader.beginObject(); } else if (JsonToken.NAME.equals(nextToken)) { String name = jsonReader.nextName(); System.out.println("Token KEY >>>> " + name); } else if (JsonToken.STRING.equals(nextToken)) { String value = jsonReader.nextString(); System.out.println("Token Value >>>> " + value); } else if (JsonToken.NUMBER.equals(nextToken)) { long value = jsonReader.nextLong(); System.out.println("Token Value >>>> " + value); } else if (JsonToken.NULL.equals(nextToken)) { jsonReader.nextNull(); System.out.println("Token Value >>>> null"); } else if (JsonToken.END_OBJECT.equals(nextToken)) { jsonReader.endObject(); } } } catch (IOException e) { e.printStackTrace(); } finally { jsonReader.close(); } } }
輸出:
Token KEY >>>> id Token Value >>>> 1001 Token KEY >>>> firstName Token Value >>>> Lokesh Token KEY >>>> lastName Token Value >>>> Gupta Token KEY >>>> email Token Value >>>> null
在上面的示例中:
Gson JsonParser用於將Json數據解析爲JsonElement的解析樹,從而解析爲JsonObject。
JsonObject可用於使用JSON字符串中的相應鍵來訪問值。
JsonParser類只有一個默認構造函數,而且不須要任何參數或配置。
JsonParser parser = new JsonParser();
JsonParser類提供3種方法來提供JSON做爲源並將其解析爲JsonElements樹。
若是指定的文本不是有效的JSON,則這三個方法都將拋出JsonParseException和JsonSyntaxException。
在JsonElement樹中解析了JSON字符串後,咱們就可使用它的各類方法來訪問JSON數據元素。
例如,使用一種類型檢查方法找出它表明什麼類型的JSON元素:
jsonElement.isJsonObject(); jsonElement.isJsonArray(); jsonElement.isJsonNull(); jsonElement.isJsonPrimitive();
咱們可使用相應的方法將JsonElement轉換爲JsonObject和JsonArray:
JsonObject jsonObject = jsonElement.getAsJsonObject(); JsonArray jsonArray = jsonElement.getAsJsonArray();
一旦有了JsonObject或JsonArray實例,就可使用其get()方法從中提取字段。
使用JsonParser將JSON解析爲JsonElement(和JsonObject),並使用鍵獲取JSON值:
import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonParser; public class Main { public static void main(String[] args) throws Exception { String json = "{'id': 1001, " + "'firstName': 'Lokesh'," + "'lastName': 'Gupta'," + "'email': 'howtodoinjava@gmail.com'}"; JsonElement jsonElement = new JsonParser().parse(json); JsonObject jsonObject = jsonElement.getAsJsonObject(); System.out.println( jsonObject.get("id") ); System.out.println( jsonObject.get("firstName") ); System.out.println( jsonObject.get("lastName") ); System.out.println( jsonObject.get("email") ); } }
輸出:
1001 "Lokesh" "Gupta" "howtodoinjava@gmail.com"
咱們可使用Gson實例及其fromJson()方法來得到相同的結果:
String json = "{'id': 1001, " + "'firstName': 'Lokesh'," + "'lastName': 'Gupta'," + "'email': 'howtodoinjava@gmail.com'}"; JsonObject jsonObject = new Gson().fromJson(json, JsonObject.class); System.out.println(jsonObject.get("id")); System.out.println(jsonObject.get("firstName")); System.out.println(jsonObject.get("lastName")); System.out.println(jsonObject.get("email"));
輸出:
String json = "{'id': 1001, " + "'firstName': 'Lokesh'," + "'lastName': 'Gupta'," + "'email': 'howtodoinjava@gmail.com'}"; JsonObject jsonObject = new Gson().fromJson(json, JsonObject.class); System.out.println(jsonObject.get("id")); System.out.println(jsonObject.get("firstName")); System.out.println(jsonObject.get("lastName")); System.out.println(jsonObject.get("email"));
這是一個完整的示例,展現瞭如何迭代從JsonReader得到的JsonElement:
JsonParser parser = new JsonParser(); String json = "{ \"f1\":\"Hello\",\"f2\":{\"f3:\":\"World\"}}"; JsonElement jsonTree = parser.parse(json); if(jsonTree.isJsonObject()){ JsonObject jsonObject = jsonTree.getAsJsonObject(); JsonElement f1 = jsonObject.get("f1"); JsonElement f2 = jsonObject.get("f2"); if(f2.isJsonObject()){ JsonObject f2Obj = f2.getAsJsonObject(); JsonElement f3 = f2Obj.get("f3"); } }
Gson在默認序列化和反序列化方面提供了很是出色的功能。
不過,咱們可能會遇到默認和內置自定義選項沒法解決咱們問題的狀況。在這種狀況下,咱們能夠經過兩個接口JsonSerializer和JsonDeserializer使用自定義序列化和反序列化。
JsonSerializer.java:
public interface JsonSerializer<T> { public JsonElement serialize(T value, Type type, JsonSerializationContext jsonSerializationContext) { } }
爲Json建立自定義序列化程序後,咱們還須要經過GsonBuilder.registerTypeAdapter(Type,Object)註冊該序列化程序。
當Gson遇到指定類型的字段時,它會在序列化期間調用其回調方法serialize()。
假設咱們遇到一種狀況,咱們必須將Java對象序列化爲json,這樣全部布爾值都應寫爲1或0,而不是打印true或false。
讓咱們爲該要求編寫自定義序列化程序。
BooleanSerializer.java:
import com.google.gson.JsonElement; import com.google.gson.JsonPrimitive; import com.google.gson.JsonSerializationContext; import com.google.gson.JsonSerializer; public class BooleanSerializer implements JsonSerializer<Boolean> { public JsonElement serialize(Boolean aBoolean, Type type, JsonSerializationContext jsonSerializationContext) { if(aBoolean){ return new JsonPrimitive(1); } return new JsonPrimitive(0); } }
讓咱們編寫一個程序,使用registerTypeAdapter()註冊JsonSerializer實例,並使用該程序將Java對象序列化爲json。
import com.google.gson.Gson; import com.google.gson.GsonBuilder; public class Main { public static void main(String[] args) throws Exception { Employee emp = new Employee(1, "Lokesh", "Gupta", "howtodoinjava@gmail.com", true); Gson gson = new GsonBuilder() .registerTypeAdapter(Boolean.class, new BooleanSerializer()) .setPrettyPrinting() .create(); String json = gson.toJson(emp); System.out.println(json); } }
注意程序輸出,鍵「 active」的值被序列化爲1:
{ "id": 1, "firstName": "Lokesh", "lastName": "Gupta", "email": "howtodoinjava@gmail.com", "active": 1 }
定製反序列化器必須實現JsonDeserializer接口。JsonDeserializer接口以下所示:
JsonDeserializer.java:
public interface JsonDeserializer<T> { public Boolean deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext jsonDeserializationContext) throws JsonParseException; }
爲Json建立自定義反序列化器以後,咱們還須要經過GsonBuilder.registerTypeAdapter(Type,Object)註冊此反序列化器。
當Gson遇到指定類型的字段時,它會在序列化期間調用其回調方法deserialize()。
假設某些服務將日期字段分別分爲天,月和年等部分分別返回給咱們。在JSON字符串中,它們可能有意義,可是在Java中,它們只有做爲單個java.time.LocalDate對象的一部分時纔有意義。
employee.json:
{ "id": 1, "firstName": "Lokesh", "lastName": "Gupta", "email": "howtodoinjava@gmail.com", "day": 11, "month": 8, "year": 2019 }
咱們要自定義反序列化並將最後三個字段組合爲LocalDate對象。
咱們的Employee看起來像這樣。包括必要的getter和setter以及構造函數。
Employee.java:
public class Employee { private Integer id; private String firstName; private String lastName; private String email; private LocalDate dob; }
自定義反序列化器類以下所示:
EmployeeDeserializer.java:
import com.google.gson.JsonDeserializationContext; import com.google.gson.JsonDeserializer; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonParseException; public class EmployeeDeserializer implements JsonDeserializer<Employee> { @Override public Employee deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { JsonObject jsonObject = json.getAsJsonObject(); LocalDate localDate = LocalDate.of( jsonObject.get("year").getAsInt(), jsonObject.get("month").getAsInt(), jsonObject.get("day").getAsInt() ); return new Employee( jsonObject.get("id").getAsInt(), jsonObject.get("firstName").getAsString(), jsonObject.get("lastName").getAsString(), jsonObject.get("email").getAsString(), localDate); } }
註冊反序列化器,而後將給定的JSON解析爲java對象:
Main.java:
public class Main { public static void main(String[] args) throws Exception { String json = "{'id': 1001," + "'firstName': 'Lokesh'," + "'lastName': 'Gupta'," + "'email': 'howtodoinjava@gmail.com', " + "'day': 11, " + "'month': 8, " + "'year': 2019}"; Gson gson = new GsonBuilder() .registerTypeAdapter(Employee.class, new EmployeeDeserializer()) .create(); Employee employee = gson.fromJson(json, Employee.class); System.out.println(employee); } }
注意程序輸出將3個單獨的字段組合到單個LocalDate對象中:
Employee [id=1001, firstName=Lokesh, lastName=Gupta, email=howtodoinjava@gmail.com, dob=2019-08-11]
參考:
【1】:Gson
【2】:Gson – Introduction
【3】:Gson – Installation
【4】:GSON - Gson
【5】:GSON – Serialize and Deserialize JSON
【6】:Gson – Pretty Printing for JSON Output
【7】:GSON – Parse JSON array to Java array or list
【8】:GSON – Serialize and deserialize JSON to Set
【9】:Gson – GsonBuilder Configuration Examples
【10】:Gson @Since – Version Support
【11】:Gson @SerializedName
【12】:Gson – JsonReader
【13】:Gson – JsonReader
【14】:Gson – JsonParser
【15】:GSON - JsonParser